Search code examples
javascriptphpsvgpngqr-code

Save QR-Code as an Image on Server-Side with Javascript/PHP


I am working on a small project where I need to generate QR code and logo inside. I need to save generated QR code in PNG or JPEG format. Below code is working fine if I use svg format. But I want to save file as PNG or JPEG format. I tried to change svg to png, it saves file but I am not able to open it. When I try to open PNG file it says unsupported format.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>QR Code Styling</title>
  <script type="text/javascript" src="https://unpkg.com/[email protected]/lib/qr-code-styling.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>

<body>
  <div id="canvas"></div>
  <script type="text/javascript">

    const qrCode = new QRCodeStyling({
      width: 300,
      height: 300,
      type: "svg",
      data: "https://www.facebook.com/",
      image: "https://upload.wikimedia.org/wikipedia/commons/5/51/Facebook_f_logo_%282019%29.svg",
      dotsOptions: {
        color: "#4267b2",
        type: "rounded"
      },
      backgroundOptions: {
        color: "#e9ebee",
      },
      imageOptions: {
        crossOrigin: "anonymous",
        margin: 20
      }
    });

    var svgBlob = qrCode.getRawData('jpeg');
    svgBlob.then(value => value.text().then(value => sendAjax(value)));

    function sendAjax(svgString) {
      $.ajax('saveqr.php', {
        'data': svgString, //canvas.innerHTML,
        'type': 'POST',
        'processData': false,
        'contentType': 'image/jpg'
      });
    }
    qrCode.append(document.getElementById("canvas"));
    // qrCode.download({ name: "qr", extension: "svg" });
  </script>
</body>

</html>

saveqr.php

<?php 
$svg = file_get_contents('php://input');
$myfile = fopen("testfile.jpeg", "w");
fwrite($myfile, $svg);

  
?>

Solution

  • Please note that JPEG and PNG files are binary format files, whereas SVG files are plain-text format files

    However, actually plain-text can be regarded as a subset of binary, so when you pass the data to PHP for saving, actually (1) you may safely remove value => value.text().then ... and (2) you may also remove the line 'contentType': 'image/xxx' in your ajax for this operation.

    So the following (for the ajax part) will all be good:

    SVG

    var svgBlob = qrCode.getRawData('svg');
        svgBlob.then(value => sendAjax(value));
    
        function sendAjax(svgString) {
          $.ajax('saveqr.php', {
            'data': svgString, //canvas.innerHTML,
            'type': 'POST',
            'processData': false,
          });
        }
    

    For JPEG

    var svgBlob = qrCode.getRawData('jpeg');
        svgBlob.then(value => sendAjax(value));
    
        function sendAjax(svgString) {
          $.ajax('saveqr.php', {
            'data': svgString, //canvas.innerHTML,
            'type': 'POST',
            'processData': false,
          });
        }
    

    For PNG

    var svgBlob = qrCode.getRawData('png');
        svgBlob.then(value => sendAjax(value));
    
        function sendAjax(svgString) {
          $.ajax('saveqr.php', {
            'data': svgString, //canvas.innerHTML,
            'type': 'POST',
            'processData': false,
          });
        }
    

    For the PHP (saveqr.php) , just make sure that the extension you pick matches the file you want to save, so

    For SVG

    ....
    $myfile = fopen("testfile1.svg", "w");
    ....
    

    For PNG

    ....
    $myfile = fopen("testfile1.png", "w");
    ....
    

    For JPG

    ....
    $myfile = fopen("testfile1.jpg", "w");
    ....
    

    or

    ....
    $myfile = fopen("testfile1.jpeg", "w");
    ....