簡體   English   中英

我如何使用谷歌 api 生成的 php 下載二維碼?

[英]how can i download a qr code using php generated by google api?

我在學校有一個項目,這是工資單,我想下載 jquery 中由谷歌 api 圖表生成的二維碼,問題是如何下載二維碼? 這是谷歌api圖表生成的代碼

var codeFile = document.getElementsByClassName('codeimg')[0].setAttribute('src', https:chart.googleapis.com/chart?cht=qr&chl=${response.employee_id}&choe=UTF-8&chs=500x500 )

這是我的html代碼和下載二維碼的代碼`

<div class="modal-dialog">
  <div class="modal-content">
    <div class="modal-header">
      <button type="button" class="close" data-dismiss="modal" aria-label="Close">
        <span aria-hidden="true">&times;</span></button>
      <h4 class="modal-title"><b><span class="employee_id"></span></b></h4>
    </div>
    <div class="modal-body">
      <form class="form-horizontal" method="POST" action="">
        <input type="hidden" class="empid" name="id">
        <div class="qr-code text-center">
          <p>QR CODE</p>
          <h2 class="del_employee_name" style="font-family: arial black;"></h2>
          <!--  <h3 id="employee_id"></h3> -->
          <img class="codeimg" height="200px" width="200px">
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-default btn-flat pull-left" data-dismiss="modal"><i class="fa fa-close"></i> Close</button>
          <button type="button" class="btn btn-primary btn-flat" name="download"><i class="fa fa-download"></i>download</button>

      </form>
      <?php
      $qrCodeData = file_get_contents($codeFile);
      $fileName = "qr_code.png";
      $filePath = "/path/to/save/img/" . $fileName;
      file_put_contents($filePath, $qrCodeData);   
      header("Content-Type: image/png");
      readfile($filePath);
      ?>
    </div>
  </div>
</div>
`

有幾種方法可以做到這一點,我將向您展示其中的一些。

在這兩個答案中,為了將遠程文件傳輸到我們的服務器,我將使用這個 SO answer提供的稍微修改過的解決方案。

<?php
    // Let's use your QR image link
    $codeFile = 'https://chart.googleapis.com/chart?cht=qr&chl=${response.employee_id}&choe=UTF-8&chs=500x500';

    // Let's also set the headers for the request
    $options = [
        "https" => [
        "method" => "GET",
        "header" => "
            Accept-language: en".PHP_EOL.
            "Cookie: foo=bar".PHP_EOL.
            "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8".PHP_EOL.
            "Connection: keep-alive"
        ]
    ];

    // https://www.php.net/manual/en/function.stream-context-create.php
    $context = stream_context_create($options);

    // https://www.php.net/manual/en/function.file-get-contents.php
    $qrCodeData = file_get_contents($codeFile, false, $context);

    $fileName = "qr_code.png";
    $filePath = "./path/to/save/img/" . $fileName;
    file_put_contents($filePath, $qrCodeData); 

    header('Content-Description: File Transfer');
    header("Content-Type: image/png");
    header('Content-Disposition: attachment; filename='.$fileName);
    header('Connection: Keep-Alive');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');

    readfile($filePath);
?>

使用$options$context以便我們可以將標頭與我們的請求一起發送到其他服務器。 為了大大簡化它,我們這樣做是為了讓我們的請求更加具體,並使遠程服務器更容易理解並知道如何處理我們的請求。

獲取文件后,我們通過指定我們自己的標頭來強制下載它。 請注意,如果您只想使用 PHP 下載文件,則標頭和文件流必須是您的服務器輸出的唯一內容。您也不應該在 HTML 的中間使用header(...) - 使用header和其他與標頭相關的函數(例如, setcookie(...) )在向客戶端/用戶輸出任何內容之前保留。 當你echo / var_dump / sprintf任何東西時,使用header(...)就太晚了。

但是,如果您確實想要 output 或 HTML,並且您想讓用戶通過單擊鏈接或按鈕來下載圖像(在我看來,通過查看您的原始代碼),那么類似這樣的事情將工作。

<?php
    // Let's use your QR image link
    $codeFile = 'https://chart.googleapis.com/chart?cht=qr&chl=${response.employee_id}&choe=UTF-8&chs=500x500';

    // Let's also set the headers for the request
    $options = [
        "https" => [
        "method" => "GET",
        "header" => "
            Accept-language: en".PHP_EOL.
            "Cookie: foo=bar".PHP_EOL.
            "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8".PHP_EOL.
            "Connection: keep-alive"
        ]
    ];

    $context = stream_context_create($options);

    // Let's supress the errors
    $qrCodeData = @file_get_contents($codeFile, false, $context);

    $fileName = "qr_code.png";
    $filePath = "./path/to/save/img/";
    $fullPath = $filePath . $fileName;
    file_put_contents($fullPath, $qrCodeData);

    // Look, Ma, no headers!
?>
<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                <span aria-hidden="true">&times;</span>
            </button>
            <h4 class="modal-title"><b><span class="employee_id"></span></b></h4>
        </div>
        <div class="modal-body">
            <form class="form-horizontal" method="POST" action="">
                <input type="hidden" class="empid" name="id">
                <div class="qr-code text-center">
                    <p>QR CODE</p>
                    <h2 class="del_employee_name" style="font-family: arial black;"></h2>
                    <!--  <h3 id="employee_id"></h3> -->
                    <img src="<?php echo $fullPath;?>" height="200px" width="200px">
                    <a id="qrImg" href="<?php echo $fullPath;?>" download="<?=$fileName?>" style="display:none"></a>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default btn-flat pull-left" data-dismiss="modal"><i class="fa fa-close"></i> Close</button>
                    <button type="button" class="btn btn-primary btn-flat" name="download" id="dlBtn"><i class="fa fa-download"></i>download</button>
                </div>
            </form>
        </div>
    </div>
</div>
<script>
    const dlBtn = document.getElementById("dlBtn");
    dlBtn.addEventListener("click",dlImg);

    function dlImg(e) {
        e.preventDefault();

        let qrImg = document.getElementById("qrImg");
        qrImg.click();
    }
</script>

興趣點:

  1. 您需要將遠程文件下載到您的服務器,並將其保存在那里,直到用戶下載它。 如果用戶關閉模式,您可能會觸發 AJAX 文件刪除(這不是一件好事,因為用戶可以簡單地關閉瀏覽器,將電源線從插座中拔出,放下手機並弄壞它,等等)。 您還可以設置一個 cronjob 來刪除這些臨時文件(例如,每天一次),以避免它們堆積起來
  2. @的使用是為了抑制可能出現的任何錯誤。 並不總是(也許永遠不會)是一件好事。 為簡單起見,此示例中使用它來避免潛在的檢查和錯誤處理。 實際上,您必須處理這些——如果文件不是幾 KB,而是幾 GB 怎么辦? 你會到處觸發致命/內存不足的錯誤
  3. 如果遠程文件很大,您應該考慮使用cURL下載。 如果您不熟悉,請在提供的鏈接上閱讀有關 cURL 的更多信息
  4. 您應該始終對下載到服務器的內容進行某種驗證——它真的是圖像嗎? 你確定這不是惡意腳本? 有多種處理方法。 一種非常簡單的方法是這樣的:
function checkImg($source) {
    // check the image size
    $size = getimagesize($source);
    if($size === false) {
        unlink($source);
        return false;
    }

    // is it really an image?
    $sourceImg = @imagecreatefromstring(@file_get_contents($source));
    if ($sourceImg === false) {
        // not an image after we convert it?
        unlink($source);
        unlink($sourceImg);
        return false;
    }

    return true;
}

// let's try it out
$isImg = checkImage($fullPath);

if(!$isImg) {
    // do something
} else {
    // do something else
}

您還可以在此基礎上引入額外的檢查(例如,分辨率是否符合您的預期);

  1. 請務必檢查caniuse以查看哪些瀏覽器支持使用download屬性(在此示例中與a href一起使用,來自您最初提供的 HTML)。 在發布此答案時,只有 Opera mini 和 IE 11 不支持download屬性,因此如果您的目標受眾不使用這些瀏覽器,您應該清楚。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM