Download File using PHP

0

I want to download a server image using PHP. Specifications:

  • I do not want to use javascript and I do not want to pass the database by name and then retrieve it.

  • The image I want to download is a QR code that I generated and saved in a "php_action / temp" directory. Within this directory there are several images, so I am trying to download only the file that I have generated.

  • I added the phpqrcode library and created a file that calls this library to generate the QR code. This file is show_product2.php in root.

     //set it to writable location, a place for temp generated PNG files
    
      session_start();
    
    $PNG_TEMP_DIR = dirname(__FILE__).DIRECTORY_SEPARATOR.'php_action'.DIRECTORY_SEPARATOR.'temp'.DIRECTORY_SEPARATOR;
    
    //html PNG location prefix
    $PNG_WEB_DIR = 'temp/';
    
    include "phpqrcode/qrlib.php";
    
    //ofcourse we need rights to create temp dir
    if (!file_exists($PNG_TEMP_DIR))
    mkdir($PNG_TEMP_DIR);
    
    
    $filename = $PNG_TEMP_DIR.'test.png';
    
    //processing form input
    //remember to sanitize user input in real-life solution !!!
    $errorCorrectionLevel = 'L';
    if (isset($_REQUEST['level']) && in_array($_REQUEST['level'], 
    array('L','M','Q','H')))
    $errorCorrectionLevel = $_REQUEST['level'];
    
    $matrixPointSize = 4;
    if (isset($_REQUEST['size']))
    $matrixPointSize = min(max((int)$_REQUEST['size'], 1), 10);
    
    
    if (isset($_REQUEST['data'])) {
    
    //it's very important!
    if (trim($_REQUEST['data']) == '')
        die('Introduzca la Referencia del Producto en el campo "Referencia" 
    y haga clic en "Generar", no puede dejar en blanco los datos! <a href="?">Regresar</a>');
      $ReferenciaProducto = $_REQUEST['data'];
    // user data
    $filename = $PNG_TEMP_DIR.$ReferenciaProducto.'-'.md5($_REQUEST['data'].'|'.$errorCorrectionLevel.'|'.$matrixPointSize).'.png';
    QRcode::png($_REQUEST['data'], $filename, $errorCorrectionLevel, $matrixPointSize, 2);
    
    
       $filename2 = $ReferenciaProducto.'-'.md5($_REQUEST['data'].'|'.$errorCorrectionLevel.'|'.$matrixPointSize).'.png';
    $_SESSION['filename']=$filename2; 
    
    } else {
    
     //default data
    echo 'La Imagen QR que aparece por defecto, es de prueba, hasta que no introduzca la referncia en el campo inferior y presione "Generar" no se visualizará la imagen definitiva"<hr/>';
    QRcode::png('PHP QR Code :)', $filename, $errorCorrectionLevel, $matrixPointSize, 2);
    
      }
    
     //display generated file
    // echo '<img src="'.$PNG_WEB_DIR.basename($filename).'" /><hr/>';
     echo '<img src="'.'php_action'.DIRECTORY_SEPARATOR.$PNG_WEB_DIR.basename($filename).'" /><hr/>';
    
    //.'php_action'.DIRECTORY_SEPARATOR.
    
    //config form
    echo '<form action="show_product2.php" method="post">
    Ref:&nbsp;<input name="data" value="'.(isset($_REQUEST['data'])? 
    htmlspecialchars($_REQUEST['data']):'Escriba  Ref.de Producto').'" />&nbsp;
    Definición:&nbsp;<select name="level">
        <option value="L"'.(($errorCorrectionLevel=='L')?' selected':'').'>L 
    - Muy Baja</option>
        <option value="M"'.(($errorCorrectionLevel=='M')?' selected':'').'>Baja</option>
        <option value="Q"'.(($errorCorrectionLevel=='Q')?' selected':'').'>Media</option>
        <option value="H"'.(($errorCorrectionLevel=='H')?' selected':'').'>Alta - La Mejor</option>
    </select>&nbsp;
    Tamaño:&nbsp;<select name="size">';
    
     for($i=1;$i<=10;$i++)
    echo '<option value="'.$i.'"'.(($matrixPointSize==$i)?' selected':'').'>'.$i.'</option>';
    
    echo '</select>&nbsp;
    <input type="submit" value="GENERAR"></form><hr/>';
    
    
    ?>
          <center>
    
    <?php echo "<form method='get' action='php_action/downloadQr.php? Descargar='".$_SESSION['filename'].">";?>
    
    echo' <button class="btn btn-default button3" data-toggle="submit"
    name="Descargar" data-target = "Descarga"><i class="glyphicon glyphicon-
     download-alt"></i> Descargar Qr en su Computadora </button>
    
      &nbsp;<button class="btn btn-default button3" data-toggle="submit"
    id="GuardarQRlBtn" data-target="#GuardarQRlBtn"> <i class="glyphicon
    glyphicon-tasks"></i> Guardar Qr en el Servidor </button></form>';
    
    
           </center>
    

I have created a function in another directory that is called to download the file. This function is in "includes / functions.php." Since in the previous code this function is called by: " includes / functions.php ";

    function descargar($fichero){

    $basefichero = basename($fichero);
    header("Content-Type: application/octet-stream");
    header("Content-Type: application/force-download");
    header("Content-Length: ".filesize($fichero));
    header("Content-Disposition:attachment; filename=" .$basefichero."");
    readfile($fichero);
      }

This is the interface screen, when you put the reference of the product and press "Generate", the code works well, because it creates the QR gives it a name followed by a random extension and stores it in my "temp" directory with png format. As seen in the image, I have put a control point that forces the program to write the reference of the image that is saved inside the variable "$ filename2" in the code.

The problem comes when I have generated the image once. that in principle I think it is saved in the variable along with its path "$ filename" and in the name of the file as I said in "$ filename2" and I press the button "Download QR on your computer" the program will search the file where are the instructions to call the download function that is the file (deleteQrTemp.php):

   <?php
    session_start();
     include "includes/functions.php";

    if(isset($_GET['Descargar'])) {

    echo $_SESSION['filename'];

     descargar($_SESSION['filename']);


       }

     ?>

As a control method I have put in this file the instruction "echo $ _SESSION ['filename'];" so that I am impressed with the name of the file that is now saved in the global variable "$ _SESSION" already in the previous file "show_product2.php" I had created for the name of the image file "$ filename2". And indeed the name of the file is received in the variable, therefore, so far so good:

Goes to the file, and starts to go through the instructions, prints again in my "echo" control the name of the file of the image, that means that it receives it, but here it stops, the blank screen is left with the name of the file but does not download the file. Therefore I think, that by elimination, the error must be in the function "download ()" but not in what fails. I have described this section above.

I appreciate any help.

    
asked by Oscar C. 15.11.2018 в 20:07
source

2 answers

0

create a new download.php? Download = filename
at the beginning of the file we place a session_start ();
then

   <?php
session_start();
   include "includes/functions.php";
   if(isset($_GET['descarga'])) {
    descargar($filename);
    }
    ?>

in the first:

<?php
//para que el nombre siempre quede guardo
session_start();

//set it to writable location, a place for temp generated PNG files
 $PNG_TEMP_DIR = dirname(__FILE__).DIRECTORY_SEPARATOR.'php_action'.DIRECTORY_SEPARATOR.'temp'.DIRECTORY_SEPARATOR;

//html PNG location prefix
$PNG_WEB_DIR = 'temp/';

include "phpqrcode/qrlib.php";

//ofcourse we need rights to create temp dir
if (!file_exists($PNG_TEMP_DIR))
mkdir($PNG_TEMP_DIR);


$filename = $PNG_TEMP_DIR.'test.png';

//processing form input
//remember to sanitize user input in real-life solution !!!
$errorCorrectionLevel = 'L';
if (isset($_REQUEST['level']) && in_array($_REQUEST['level'], 
array('L','M','Q','H')))
$errorCorrectionLevel = $_REQUEST['level'];

$matrixPointSize = 4;
if (isset($_REQUEST['size']))
$matrixPointSize = min(max((int)$_REQUEST['size'], 1), 10);


if (isset($_REQUEST['data'])) {

//it's very important!
if (trim($_REQUEST['data']) == '')
    die('Introduzca la Referencia del Producto en el campo "Referencia" 
y haga clic en "Generar", no puede dejar en blanco los datos! <a href="?">Regresar</a>');
  $ReferenciaProducto = $_REQUEST['data'];
// user data
$filename = $PNG_TEMP_DIR.$ReferenciaProducto.'-'.md5($_REQUEST['data'].'|'.$errorCorrectionLevel.'|'.$matrixPointSize).'.png';
$_SESSION["filename"] = $filename;
QRcode::png($_REQUEST['data'], $filename, $errorCorrectionLevel, $matrixPointSize, 2);

} else {

 //default data
echo 'La Imagen QR que aparece por defecto, es de prueba, hasta que no introduzca la referncia en el campo inferior y presione "Generar" no se visualizará la imagen definitiva"<hr/>';
QRcode::png('PHP QR Code :)', $filename, $errorCorrectionLevel, $matrixPointSize, 2);

  }

 //display generated file
// echo '<img src="'.$PNG_WEB_DIR.basename($filename).'" /><hr/>';
 echo '<img src="'.'php_action'.DIRECTORY_SEPARATOR.$PNG_WEB_DIR.basename($filename).'" /><hr/>';

//.'php_action'.DIRECTORY_SEPARATOR.

//config form
echo '<form action="show_product2.php" method="post">
Ref:&nbsp;<input name="data" value="'.(isset($_REQUEST['data'])? 
htmlspecialchars($_REQUEST['data']):'Escriba  Ref.de Producto').'" />&nbsp;
Definición:&nbsp;<select name="level">
    <option value="L"'.(($errorCorrectionLevel=='L')?' selected':'').'>L 
- Muy Baja</option>
    <option value="M"'.(($errorCorrectionLevel=='M')?' selected':'').'>Baja</option>
    <option value="Q"'.(($errorCorrectionLevel=='Q')?' selected':'').'>Media</option>
    <option value="H"'.(($errorCorrectionLevel=='H')?' selected':'').'>Alta - La Mejor</option>
</select>&nbsp;
Tamaño:&nbsp;<select name="size">';

 for($i=1;$i<=10;$i++)
echo '<option value="'.$i.'"'.(($matrixPointSize==$i)?' selected':'').'>'.$i.'</option>';

echo '</select>&nbsp;
<input type="submit" value="GENERAR"></form><hr/>';


?>
  <center>        


   <?php
//validamos que el nombre del archivo exista en la varible de session

   if(isset($_SESSION["filename"])) {
      echo "<form method='get' action='download.php?descarga='".$_SESSION["filename"].">";

echo' <button class="btn btn-default button3" data-toggle="submit" 
name="Descargar" data-target = "Descarga"><i class="glyphicon glyphicon- 
  download-alt"></i> Descargar Qr en su Computadora </button>

  &nbsp;<button class="btn btn-default button3" data-toggle="submit" 
id="GuardarQRlBtn" data-target="#GuardarQRlBtn"> <i class="glyphicon 
glyphicon-tasks"></i> Guardar Qr en el Servidor </button></form>';
    ?>
</center>
    
answered by 15.11.2018 / 20:57
source
0

When you press the Download button, the form that includes it is launched, and it takes you to the same file that you are running. The entire page is being reloaded, and although at that moment Descargar is defined, the file headers that you have in the download () function are NOT SENT, since the html forms that make up your web page have already been sent.

I suggest 2 ways:

That the action to download is in another file:

generates a file (eg: downloadQr.php ) with the following content:

<?php
  include "includes/functions.php";
  $PNG_TEMP_DIR = dirname(__FILE__).DIRECTORY_SEPARATOR.'php_action'.DIRECTORY_SEPARATOR.'temp'.DIRECTORY_SEPARATOR;
  //ofcourse we need rights to create temp dir
  if (!file_exists($PNG_TEMP_DIR))
      mkdir($PNG_TEMP_DIR);

  $filename = $PNG_TEMP_DIR.'test.png';
  if(isset($_GET['Descargar'])) {
    descargar($filename);
  }
?>

and in your form that contains the call of the Download button, change the action to this new file. Something like:

  <form method="get" action="downloadQr.php">

 <button class="btn btn-default button3" data-toggle="submit" 
name="Descargar" data-target = "Descarga"><i class="glyphicon glyphicon- 
  download-alt"></i> Descargar Qr en su Computadora </button>
</form>

With this, when you press the Download button, the download action of the file is called in downloadQr.php. It will send the headers that you define in the function, and it will download the file.

Manage the download call at the beginning of your file: Change the management of creating the file, towards the beginning of your code. Put the first thing of all this:

<?php
  include "includes/functions.php";
  $PNG_TEMP_DIR = dirname(__FILE__).DIRECTORY_SEPARATOR.'php_action'.DIRECTORY_SEPARATOR.'temp'.DIRECTORY_SEPARATOR;
  //ofcourse we need rights to create temp dir
  if (!file_exists($PNG_TEMP_DIR))
      mkdir($PNG_TEMP_DIR);

  $filename = $PNG_TEMP_DIR.'test.png';
  if(isset($_GET['Descargar'])) {
    descargar($filename);
  } else {
 ?>

Please note that I have set a else , this is so you can see first if it is defined to download and ONLY make the download (sending the file headers). This else must be closed at the end of your file, so that, if you have not asked to download the QR, it will show you the rest of your action.

MY RECOMMENDATION:

This whole problem comes up because you mix html and php process, and it is not very clear (and it is difficult) to organize these things. I would recommend that you start using MVC, review or use some framework (type symfony, codeigniter, laravel) to see how the processes are organized in controllers and views.

    
answered by 15.11.2018 в 20:47