Adding an image to ZipArchive from mysql blob database - php

I have recently discovered ZipArchive for PHP, i have no problem adding files or files from strings however i have an image blob inside a MySQL database that i want to add to the ZipArchive. I can get the image in a separate file and i can also get it to download as a jpg. I want to be able to add the image into the archive.
The below code shows how i access my BLOB
header('Content-Type: image/jpg; charset=utf-8');
// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');
$conB = mysql_connect("localhost", "user_name", "user_pass");//connect to the database
if (!$conB)
{
die('Could not connect: ' . mysql_error()); // if cannot connect then send error message
}
mysql_select_db("binary", $conB); // define database name
$id = $_GET['ids'];
$query = mysql_query("SELECT * FROM tbl_images WHERE ID ='".$id."' ");
while($row = mysql_fetch_array($query))
{
$content = $row['image'];
header('Content-Disposition: attachment; filename=image"'.$row['ID'].'".jpg');
fwrite($output, $content);
}
That all works fine for me, the below code shows how i am adding a file to a zip archive
$zip = new ZipArchive();
$ZipFileName = "newZipFile.zip";
if ($zip->open($ZipFileName, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) !== true)
{
echo "Cannot Open for writing";
}
$zip->addEmptyDir('newFolder');
$zip->addFromString('text.txt', 'text file');
$zip->close();
//then send the headers to foce download the zip file
header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=$ZipFileName");
header("Pragma: no-cache");
header("Expires: 0");
readfile($ZipFileName);
Does any one know how i can implement them together?
If you need any more information then i can provide it :)

You can create the ZipArchive and then add the image(s) from a loop using addFromString() method. I use snippet from both your source codes below. The database connection logic is left out for simplicity reasons.
$zip = new ZipArchive();
$ZipFileName = "newZipFile.zip";
if ($zip->open($ZipFileName, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) !== true)
{
echo "Cannot Open for writing";
}
$zip->addEmptyDir('newFolder');
$query = mysql_query("SELECT * FROM tbl_images WHERE ID ='".$id."' ");
while($row = mysql_fetch_array($query))
{
$zip->addFromString( $row['image_name'], $row['image']);
}
$zip->close();

Related

How to create a zip file with PDF files with the addFromString function in php?

I have this code broken down into two parts:
The first one create me a zip file empty and download it.
The second one download me from my database a PDF file that I decoded in base64.
Both work well separately. I would like to be able to merge them and download in zip format two PDF files that are in my database.
I would like to use the addFromString function to not create a folder on my server but to download the zip file directly for the user.
Can you help me please?
Thanks for your help
<?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/www\Dylan/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();
}
?>
You need to loop through your database rows and add each piece of decoded file data to the zip file. Then download the zip at the end.
For example:
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";
}

PHP Zip unable to close()

I'm trying to get a couple files from wordpress /uploads folder using php and I get this error:
Warning: ZipArchive::close(): Can't remove file: No such file or directory in /www/public_html/wp-content/plugins/insert-php-code-snippet/shortcode-handler.php(65) : eval()'d code on line 32 (relative to $zip->close(); and bellow "if")
I use a plugin to inject PHP on the page.
I basically have a couple dozens checkboxes that when I press "Generate", it gets the name of the file like 07/2019/blabla (with code I get uploads folder + extension, checkbox only hold the media location + name file).
I checked and it's creating the Zip on /uploads, .pdf files exist but it crashes on the close part and when I download and try to extract I get the archive is either in unknown format or damaged
Any advise please?
if(isset($_POST['files'])) {
$error = ""; //error holder
$upload_dir = wp_upload_dir();
if(isset($_POST['createzip'])){
$post = $_POST;
if(isset($post['files']) and count($post['files']) > 0){
// open zip
$zip_file = $upload_dir['basedir'].'/'.time().".zip";
$zip_name = time().".zip";
$zip = new ZipArchive();
if ($zip->open($zip_file, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) !== TRUE) {
$error .= ("An error occurred creating your ZIP file.<br>");
}
foreach ($post['files'] as $file) {
// generate filename to add to zip
$filepath = $upload_dir['basedir'].'/' . $file . '.pdf';
if (file_exists($filepath)) {
$zip->addFile($filepath) or $error .= ("ERROR: Could not add the file $filename<br>");
} else {
$error .= ("File $filepath doesnt exit.<br>");
}
}
$zip->close();
if ($zip->close() !== true ) {
die($zip->getStatusString()."\n");
}
if(file_exists($zip_file)){
$error .= $zip_file;
ob_end_clean();
// push to download the zip
header('Content-type: application/zip');
header('Content-Disposition: attachment; filename="'.$zip_name.'"');
header("Content-Length: " . filesize($zip_file));
readfile($zip_file);
unlink($zip_file);
}
}
}
}
echo $error;
After $zip->close(); I replaced all code for this:
if(file_exists($zip_file)){
header($_SERVER['SERVER_PROTOCOL'].' 200 OK');
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: Binary");
header("Content-Length: ".filesize($zip_file));
header("Content-Disposition: attachment; filename=\"".basename($zip_file)."\"");
readfile($zip_file);
unlink($zip_file);
exit;
}

how to archive download multiple files from database in php

Actually i got the zipfile. But i did't need total files from the table.i want to selected userid files... I try to code bellow, i used php and mysql.
<?php
function zipFilesAndDownload($file_names,$archive_file_name,$file_path)
{
$zip = new ZipArchive();
if ($zip->open($archive_file_name, ZIPARCHIVE::CREATE )!==TRUE) {
exit("cannot open <$archive_file_name>\n");
}
foreach($file_names as $files)
{
$zip->addFile($file_path.$files,$files);
//echo $file_path.$files,$files."<br />";
}
$zip->close();
header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=$archive_file_name");
header("Pragma: no-cache");
header("Expires: 0");
readfile("$archive_file_name");
exit;
}
require_once("config.php");
$cqurfetch=mysql_query("SELECT * FROM albums where user_id='$user_id' and accept='1'");
while($row = mysql_fetch_array($cqurfetch))
{
$file_names[] = $row['user_album_images'];
}
$archive_file_name=time().'.gallery.zip';
$file_path="/uploads/";
zipFilesAndDownload($file_names,$archive_file_name,$file_path);
?>
After Many trails i have got one answer for your question.
Only 'user_id' files are zipped and stored in that zip folder.
Example:-
<?php
require_once("config.php");
$user_id = 49 ; //Just For your reference
$accept = 1 ; //Just For your reference
$sql = "SELECT * FROM albums where user_id='$user_id' and accept='$accept'";
$result = $con->query($sql);
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
$array[] = $row["user_album_images"];
echo "user_album_images: " .$row["user_album_images"]. "<br>"; //This is also just for your reference
}
}
else{
echo "fail";
}
$file= "/uploads/gallery.zip"; //Zip file path
$zip = new ZipArchive;
echo "*****zip started.*****\n";
if ($zip->open($file, ZipArchive::CREATE) === TRUE) {
foreach($array as $key => $value)
{
$zip->addFile("/".$value);
}
$zip->close();
echo '^^^^^^Zip ended^^^^^^';
}
?>
I have tested this code in my local system,this is working as like your requirement.
Hope this helps

PHP output empty ZIP

This script successfully generated the pdfs to a folder tmp/....
However the ZIP output to the browser is empty and I don't know what I have done wrong.
$file = tempnam("tmp", "zip");
$zip = new ZipArchive();
// Zip will open and overwrite the file, rather than try to read it.
$zip->open($file, ZipArchive::OVERWRITE);
foreach( explode( ',', $_POST["ids"]) as $Client_ID)
{
$sql_qry="select *
from ca_client_statement
where client_id='".$Client_ID."' and trading_period_month like '".$TP_Month."'";
$sql_err_no=sql_select($sql_qry,$sql_res,$sql_row_count,$sql_err,$sql_uerr);
//echo $sql_qry;
//echo '<br/>';
$row = mysql_fetch_assoc($sql_res);
$file_content = $row['pdf_statement'];
$file_name = 'tmp/'.$Client_ID.'statement.pdf';
$pdf=file_put_contents($file_name, $file_content);
$zip->addFile($pdf);
}
$zip->close();
// Stream the file to the client
header("Content-Type: application/zip");
header("Content-Length: " . filesize($file));
header("Content-Disposition: attachment; filename=\"a_zip_file.zip\"");
readfile($file);
unlink($file);
file_put_contents() returns the number of bytes written, not the file name. Try changing the line right after it to this:
$zip->addFile($file_name);

Zip multiple database PDF blob files

I have a database table that contains numerous PDF blob files. I am attempting to combine all of the files into a single ZIP file that I can download and then print.
Please help!
<?php
include '../config.php';
include '../connect.php';
$session = $_GET['session'];
$query = "SELECT $tbl_uploads.username, $tbl_uploads.description,
$tbl_uploads.type, $tbl_uploads.size, $tbl_uploads.content,
$tbl_members.session
FROM $tbl_uploads
LEFT JOIN $tbl_members
ON $tbl_uploads.username = $tbl_members.username
WHERE $tbl_members.session = '$session'";
$result = mysql_query($query) or die('Error, query failed');
$files = array();
while(list($username, $description, $type, $size, $content) =
mysql_fetch_array($result)) {
$files[] = "$username-$description.pdf";
}
$zip = new ZipArchive;
$zip->open('file.zip', ZipArchive::CREATE);
foreach ($files as $file) {
$zip->addFile($file);
}
$zip->close();
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename=filename.zip');
header('Content-Length: ' . filesize($zipfilename));
readfile($zipname);
exit();
?>
Your PDF data is stored in the database in BLOB fields, I don't see you putting this data in a file. So your ZIP will not contain any files because you don't add real existing files to it.
This is what you are currently doing:
Reading your data from the database
Creating an array of filenames
Creating a ZIP of filenames that might not exist
This what you should do:
Reading your data from the database
Creating an array of filenames
Write your BLOB data into that files
Creating a ZIP of files that exist
Example:
$files = array();
while(list($username, $description, $type, $size, $content) =
mysql_fetch_array($result)) {
$files[] = "$username-$description.pdf";
// write the BLOB Content to the file
if ( file_put_contents("$username-$description.pdf", $content) === FALSE ) {
echo "Could not write PDF File";
}
}
What you should do if that works for you:
Write the files in a temporary folder (maybe with some help of http://php.net/tempnam) somewhere else and maybe remove them after your archiving process.
There is also a second problem in your code, you use $zipfilename for calculating the content-length and $zipname to read the file and no variable to create the zip. Since $zipfilename and $zipname is not defined, this won't work.
You should define $zipfilename with a ZIP filename and also use that same variable when creating the zip file.
Example:
// a temp filename containing the current unix timestamp
$zipfilename = 'temp_' . time() . '.zip';
$zip->open($zipfilename, ZipArchive::CREATE);
foreach ($files as $file) {
$zip->addFile($file);
}
$zip->close();
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename=filename.zip');
header('Content-Length: ' . filesize($zipfilename));
readfile($zipfilename);
pdftk will merge multiple PDF files, as well as PDFsam..

Categories