Как создать zip-файл с файлами PDF с помощью функции addFromString в php?

#php #mysql #zip

Вопрос:

У меня этот код разбит на две части:

  • Первый создает мне пустой zip-файл и загружает его.
  • Второй загружает мне из моей базы данных PDF-файл, который я расшифровал в base64.

Оба хорошо работают по отдельности. Я хотел бы иметь возможность объединить их и загрузить в формате zip два файла PDF, которые находятся в моей базе данных.

Я хотел бы использовать addFromString функцию, чтобы не создавать папку на моем сервере, а загружать zip-файл непосредственно для пользователя.

Не могли бы вы мне помочь, пожалуйста? Спасибо за вашу помощь

 <?php


include '../include/classe_PDO.php';

$suivi = $_POST['suivi'];

// //ZIP PART
//Name zip folder with date
$dirzip = date('Ymd His')."_andromeda";

// Zip creation        
$nomzip = "C:/wamp64/wwwDylan/SAV/final/include/$dirzip.zip"; 
$zip = new ZipArchive;
if($zip -> open($nomzip, ZipArchive::CREATE ) === TRUE)
{ 
    $dir = opendir($chemin); 
    while($fichier = readdir($dir)) 
    { 
        if(is_file($chemin.$fichier)) 
        { 
          $zip -> addFromString($file, $decoded);
        } 
    } 
    $zip ->close(); 
} 

//Zip download
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="'.basename($nomzip).'"');
header('Content-Length: ' . filesize($nomzip));

flush();
readfile($nomzip);  
         

//DOWNLOAD PART
 try {
  // Connect to db
  $db = new db('mysql:dbname=jotform; host=localhost', 'root', '');
  $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  // Set SQL
  $sql = "SELECT * FROM `dhl` WHERE `submission_id` = :suivi";

  // Prepare query
  $query = $db->prepare($sql);

  // Execute query
  $query->execute(array(':suivi' => $suivi));

  foreach  ($query as $row) {
    
          $filedata = $row['label_envoi']; //get base64 data from query result
          $decoded = base64_decode($filedata); //decode base64 to binary

          $filedata2 = $row['label_retour']; //Second column
          $decoded2 = base64_decode($filedata2); 
          
          //set suitable HTTP response headers
          header('Content-Description: File Transfer'); 
          header('Content-Type: application/octet-stream'); 
          header('Content-Disposition: attachment; filename="label.pdf"');
          header('Expires: 0'); 
          header('Cache-Control: must-revalidate'); 
          header('Pragma: public'); 
          //output the binary file data in the body of the response
          echo $decoded;
          
  }


} catch (PDOException $e) {
  echo 'Error: ' . $e->getMessage();
}        



?>
 

Комментарии:

1. Вместо addFile() того, чтобы использовать addFromString()

2. Но как мне добавить два моих файла $decode и $decode2 в мой zip? Я добавил переменную $ chemin для тестирования, но мои файлы находятся в моей базе данных

3. Вы бы перебирали базу данных и вызывали addFromString каждую строку

4. Я только что изменил свой SQL-запрос, чтобы избежать SQL-инъекций, спасибо. Я понимаю, что вы имеете в виду, говоря о цикле создания zip, но я не понимаю, что именно я должен добавить…

5. Другой способ взглянуть на это заключается в том, что вам нужно включить биты для добавления в Zip-файл в код цикла вашей базы данных (а не наоборот, если это проще представить). Я добавил полный пример кода в качестве ответа ниже, я думаю, он должен работать, хотя, конечно, у меня нет реального способа его протестировать.

Ответ №1:

Вам нужно перебирать строки вашей базы данных и добавлять каждую часть декодированных данных файла в zip-файл. Затем загрузите zip-файл в конце.

Например:

 include '../include/classe_PDO.php';

$suivi = $_POST['suivi'];

// //ZIP PART
//Name zip folder with date
$dirzip = date('Ymd His')."_andromeda";

// Zip creation        
$nomzip = "C:/wamp64/www/Dylan/SAV/final/include/$dirzip.zip"; 
$zip = new ZipArchive;

if ($zip->open($nomzip, ZipArchive::CREATE ) === TRUE)
{
  try {
    //connect to DB
    $db = new db('mysql:dbname=jotform; host=localhost', 'root', '');
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    //prepare and execute query
    $sql = "SELECT * FROM `dhl` WHERE `submission_id` = :suivi";
    $query = $db->prepare($sql);
    $query->execute(array(':suivi' => $suivi));

    foreach ($query as $row) {
      //decode base64 to binary
      $decoded = base64_decode($row['label_envoi']); 
      $decoded2 = base64_decode($row['label_retour']);
    
      //add to zip
      //N.B. if there could be more than one row returned by the database, you'll need to ensure the PDFs have unique names instead of these hard-coded ones
      $zip->addFromString("label1.pdf", $decoded);
      $zip->addFromString("label2.pdf", $decoded2);
    }
  }
  catch (PDOException $e) {
    echo 'Error: ' . $e->getMessage();
  }

  $zip ->close();

  //Zip download
  header('Content-Type: application/zip');
  header('Content-Disposition: attachment; filename="'.basename($nomzip).'"');
  header('Content-Length: ' . filesize($nomzip));

  flush();
  readfile($nomzip);
}
else
{
  echo "Error - Zip file could not be created";
}
 

Комментарии:

1. Спасибо за ответ и пояснения. Я только что протестировал код, есть две вещи: первая: zip-файл хорошо создается на сервере с двумя файлами в нем, но у меня он есть на сервере, тогда как он мне не нужен… Во-вторых, zip-файл, загруженный пользователю, остается пустым, в то время как правильный на сервере

2. I have it on the server whereas I do not want it …вам нужно будет использовать задание cron для периодического удаления сгенерированных zip-файлов. Насколько я знаю, вы не можете создавать их на лету, по крайней мере, с помощью библиотеки ZipArchive.

3. Пустой zip-файл при загрузке на самом деле не имеет никакого смысла, хотя, если он заполнен на сервере, он должен быть заполнен на клиенте — это точно такой же контент, который обслуживается. Вы не делаете ничего странного на стороне клиента, например, загружаете файл через AJAX или что-то еще, не так ли?

4. Хорошо, я сделаю это с помощью запланированной задачи для удаления. Я согласен с вами, это странно, нет, моя страница очень простая, это просто ввод, в котором пользователь вводит номер отслеживания и проверяет, чтобы получить соответствующие файлы

5. Не беспокойтесь. Я также пропустил это из оригинала.