-1

I'm trying to use an API that generates QR Code images and download the generated image using PHP. This is what I have so far:

function generateQrCode($message){
    $url = 'https://backend.com/qr/create-image';
    $data = array("message" => $message);
    $postdata = json_encode($data);
    $ch = curl_init($url); 
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
    $result = curl_exec($ch);
    curl_close($ch);
    $file = fopen("qr_code_image.jpg","w");
    fwrite($file,$result);
}

I checked the backend (the application that generates the QR Code) and the image is being correctly generated and returned but I'm not being able to download the image as a JPG file from the PHP side. Using CURL to the API:

curl --location --request POST 'https://backend.com/qr/create-image' \
--header 'Content-Type: application/json' \
--data-raw '{
    "message":"123"
}'

When I call the API via Postman, I can see the image correctly. But when I call it via PHP, I cannot download the image as a file

  • "*I'm not being able to download the image as a JPG file from the PHP side*" - what does this mean? What are you trying to do, and what happens? Where are you trying to use the file your curl writes? – Don't Panic Mar 15 '22 at 02:34
  • This is a PHP application running on a Hostgator server. I implemented a button there to generate a QR Code image based on some data. So, when the user clicks on the button, I'm calling an API that generates the image and returns it as a BLOB file, and then, I want to download this blob as a JPG file in the user's machine. – Marcos Paulo Júnior Mar 15 '22 at 02:37
  • ... and? Where is that code? What happens when you try it? – Don't Panic Mar 15 '22 at 02:38
  • When I click on the button, the backend is correctly called(backend returns HTTP status 200) but I'm not being able to download the generated image. – Marcos Paulo Júnior Mar 15 '22 at 02:40
  • This is all the code that I have so far to execute the procedure. I'm going to add an example to the API call using CURL – Marcos Paulo Júnior Mar 15 '22 at 02:41
  • What is the data format of the return value from the server `$result`? Likely it is not only a jpeg raw data but may have it wrapped in json or some other format. Can you check that? – GetSet Mar 15 '22 at 02:50
  • I'm using the same API in another website(made using React and JS). This is the code to download the image and as far as I know, I'm only returning the image itself. let res = await axios.post( `${process.env.BASE_URL2}/qr/create-image`, { message: content, }, { responseType: 'blob', } ); return res['data']; Then, I use this code to convert blob to base64 string: ``` const reader = new FileReader(); reader.onloadend = () => resolve(reader.result); reader.readAsDataURL(blob); ``` – Marcos Paulo Júnior Mar 15 '22 at 03:14
  • Try: **curl** [your link and parameters] `--output qr_code_image.jpg` – Ken Lee Mar 15 '22 at 03:16
  • @KenLee I tried this locally via terminal and it worked – Marcos Paulo Júnior Mar 15 '22 at 03:18
  • Great so it solved your problem, right ? – Ken Lee Mar 15 '22 at 03:19
  • @KenLee Not exactly, I need to do it via PHP ( when the user clicks on a button), not locally via terminal – Marcos Paulo Júnior Mar 15 '22 at 03:20
  • Then just amend the curl statement to PHP counter parts. Simple, right ? – Ken Lee Mar 15 '22 at 03:20
  • @KenLee, sorry but I don't exactly understand what you mean by amend the curl statement – Marcos Paulo Júnior Mar 15 '22 at 03:23
  • 2
    First, generate the file, then download it thru PHP. You may refer to this [SO-link](https://stackoverflow.com/questions/7263923/how-to-force-file-download-with-php) or similar posts – Ken Lee Mar 15 '22 at 03:25
  • @KenLee, ok thanks. I'll try it out – Marcos Paulo Júnior Mar 15 '22 at 03:27
  • @KenLee, I've just checked the server and the image was actually correctly downloaded there. Now I need to send the image from the server to the user's machine – Marcos Paulo Júnior Mar 15 '22 at 03:36
  • 3
    Bro, there are lots of tutorials (including SO posts) telling you how to force download a JPEG file thru php, please try to find one suitable for your case – Ken Lee Mar 15 '22 at 04:36

1 Answers1

1

This is how I solved my problem:

function cleanQrCodeImagesFolder($directoryUrl){
    // delete old images to reduce my costs with hosted images
    if(file_exists($directoryUrl)){
        $files = glob($directoryUrl."*"); // get all file names
        foreach($files as $file){ // iterate files
          if(is_file($file)) {
            unlink($file); // delete file
          }
        }
    }
}
function generateQrCode($message,$dataId){
    // path to save the image
    $directoryOutput = "../img/qrcode";
    cleanQrCodeImagesFolder($directoryOutput."/");
    $urlOutput = $directoryOutput."/image_".$dataId.".jpg";
    // make http request
    $url = 'https://backend.com/qr/create-image';
    $data = array("message" => $message);
    $postdata = json_encode($data);
    $ch = curl_init($url); 
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
    curl_setopt($ch, CURLOPT_VERBOSE, 1);
    $result = curl_exec($ch);
    curl_close($ch);
    // save image locally (server)
    $file = fopen($urlOutput,"wb");
    fwrite($file,$result);
    ?>
    <script type="text/javascript">
        // send image to client's machine
        const fileUrl = <?=json_encode($urlOutput, JSON_HEX_TAG | JSON_HEX_AMP )?>;
        const directoryPath = <?=json_encode($directoryOutput, JSON_HEX_TAG | JSON_HEX_AMP )?>;
        let a = document.createElement('a')
        a.href = fileUrl
        a.download = fileUrl.replace(directoryPath,"").substr(1)//clean downloaded filename
        a.click()
    </script>
    <?php

}

Ps I also had to create the folder qrcode manually in my server