sww Posted April 7, 2018 Posted April 7, 2018 Hey there, i am knocking my brain out here … I am trying to generate a zip file based on image paths coming from a url parameter. Ended up using the zipArchive standard like this way: https://itsolutionstuff.com/post/php-how-to-create-zip-file-and-download-using-ziparchive-example.html. Also tried this method https://processwire.com/api/ref/wire-file-tools/zip/ before … UNF without any luck on both methods. All I am getting is a zip file with zero bytes. No errors appear. I think the file isn't even been created in the first place and it is just downloading the defined zip file coming from $fileName Here is my code: <?php $lb_images = "[".htmlentities($_GET['images'])."]"; // $lb_images = ['/site/assets/files/1062/image-1.jpg','/site/assets/files/1062/image-2.jpg','/site/assets/files/1062/image-3.jpg', ...] function createZip($files_ = array(), $destination = '', $overwrite = false) { if(file_exists($destination) && !$overwrite) { return false; } $validFiles = []; if(is_array($files_)) { foreach($files_ as $file) { if(file_exists($file)) { $validFiles[] = $file; } } } if(count($validFiles)) { $zip = new ZipArchive(); if($zip->open($destination,$overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) { return false; } foreach($validFiles as $file) { $zip->addFile($file,$file); } $zip->close(); return file_exists($destination); }else{ return false; } } $fileName = 'my_zip_'.time().'.zip'; $files_to_zip = $lb_images; $result = createZip($files_to_zip, $fileName); header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename=' . $fileName); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($fileName)); ob_clean(); flush(); readfile($fileName); exit; ?>
tpr Posted April 7, 2018 Posted April 7, 2018 My guess is that you would need to supply full absolute paths instead relative ones. 2
kongondo Posted April 8, 2018 Posted April 8, 2018 Here's a ProcessWire 3 example. ProcessWire does all the heavy lifting regarding headers, etc. Please see comments in the code and the assumptions made. In this example, we assume a download link is present on the page. Modify the code to suit your needs, if you find it useful . <?php namespace ProcessWire; // @todo: you can add an Array $options parameter to pass to $files->zip() function createZip($zipfile = '', $filesToZip = array()) { // @see: https://processwire.com/api/ref/files/ $files = wire('files'); // @todo: error checks here, e.g. if $zipfile (destination) is empty; // save zipped files to disk // @see: https://processwire.com/api/ref/files/zip/ $files->zip($zipfile, $filesToZip); // force download of zipped files // @see: https://processwire.com/api/ref/files/send/ $files->send($zipfile, array( 'forceDownload' => true, 'exit' => false )); // delete zip file on server after download unlink($zipfile); exit; } $result = array(); $imagesArray = array(); $zipImages = array(); // grab and sanitize image names string in $_GET parameter 'images' // in this example, names are comma-separated $images = $sanitizer->entities($input->get->images); // if we have a 'get' input if($images) { // create array of image names (array('image-1.jpg', 'image2.jpg')) etc $imagesArray = explode(',', $images); // sanitize each image name as per ProcessWire filename expectations $imagesArray = $sanitizer->array($imagesArray, 'filename'); // if we got an array of sanitized image names if(count($imagesArray)) { // get the image repository // in this example, we store all images in one page in... // ... an image field named 'images' $imagesPage = $pages->get("/zip-files/zip-file-images/"); // create selector to find images requested in $_GET // this example assumes $_GET parameter 'images' contains image basenames // @note: we make sure image names are lowercase // selector: "basename=image-1.jpg|image2.jpg" $imagesSelector = mb_strtolower(implode('|', $imagesArray)); $images = $imagesPage->images->find("basename={$imagesSelector}"); // if we got a match if($images->count) { // create array of full disk paths to the image files $zipImages = $images->explode('filename'); // just making sure we got an array back if(count($zipImages)) { // name of zip file to create (or update) $zipfile = $config->paths->assets . "my_zip_".time().".zip"; // create zip file + force download //$result = createZip($zipfile, $zipImages); createZip($zipfile, $zipImages); } } } } // assuming $_GET will contain image basenames $downloadImagesLink = "/zip-files/zip-file-test/?images=abstract.jpg,Tree-Wide.jpg,fashion.jpg,dessert.jpg,citrus_fun.jpg"; ?> <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title><?php echo $page->title; ?></title> <link rel="stylesheet" type="text/css" href="<?php echo $config->urls->templates?>styles/main.css" /> </head> <body> <h1><?php echo $page->title; ?></h1> <?php $out = "<p>Download Zipped Images</p>"; $out .= "<p><a href='{$downloadImagesLink}'>Click to download</a></p>"; echo $out; ?> </body> </html> 5
sww Posted April 8, 2018 Author Posted April 8, 2018 9 hours ago, tpr said: My guess is that you would need to supply full absolute paths instead relative ones. tried full path too … 6 hours ago, kongondo said: Here's a ProcessWire 3 example. ProcessWire does all the heavy lifting regarding headers, etc. Please see comments in the code and the assumptions made. In this example, we assume a download link is present on the page. Modify the code to suit your needs, if you find it useful . <?php namespace ProcessWire; // @todo: you can add an Array $options parameter to pass to $files->zip() function createZip($zipfile = '', $filesToZip = array()) { // @see: https://processwire.com/api/ref/files/ $files = wire('files'); // @todo: error checks here, e.g. if $zipfile (destination) is empty; // save zipped files to disk // @see: https://processwire.com/api/ref/files/zip/ $files->zip($zipfile, $filesToZip); // force download of zipped files // @see: https://processwire.com/api/ref/files/send/ $files->send($zipfile, array( 'forceDownload' => true, 'exit' => false )); // delete zip file on server after download unlink($zipfile); exit; } $result = array(); $imagesArray = array(); $zipImages = array(); // grab and sanitize image names string in $_GET parameter 'images' // in this example, names are comma-separated $images = $sanitizer->entities($input->get->images); // if we have a 'get' input if($images) { // create array of image names (array('image-1.jpg', 'image2.jpg')) etc $imagesArray = explode(',', $images); // sanitize each image name as per ProcessWire filename expectations $imagesArray = $sanitizer->array($imagesArray, 'filename'); // if we got an array of sanitized image names if(count($imagesArray)) { // get the image repository // in this example, we store all images in one page in... // ... an image field named 'images' $imagesPage = $pages->get("/zip-files/zip-file-images/"); // create selector to find images requested in $_GET // this example assumes $_GET parameter 'images' contains image basenames // @note: we make sure image names are lowercase // selector: "basename=image-1.jpg|image2.jpg" $imagesSelector = mb_strtolower(implode('|', $imagesArray)); $images = $imagesPage->images->find("basename={$imagesSelector}"); // if we got a match if($images->count) { // create array of full disk paths to the image files $zipImages = $images->explode('filename'); // just making sure we got an array back if(count($zipImages)) { // name of zip file to create (or update) $zipfile = $config->paths->assets . "my_zip_".time().".zip"; // create zip file + force download //$result = createZip($zipfile, $zipImages); createZip($zipfile, $zipImages); } } } } // assuming $_GET will contain image basenames $downloadImagesLink = "/zip-files/zip-file-test/?images=abstract.jpg,Tree-Wide.jpg,fashion.jpg,dessert.jpg,citrus_fun.jpg"; ?> <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title><?php echo $page->title; ?></title> <link rel="stylesheet" type="text/css" href="<?php echo $config->urls->templates?>styles/main.css" /> </head> <body> <h1><?php echo $page->title; ?></h1> <?php $out = "<p>Download Zipped Images</p>"; $out .= "<p><a href='{$downloadImagesLink}'>Click to download</a></p>"; echo $out; ?> </body> </html> thanks … will try it out asap.
sww Posted April 8, 2018 Author Posted April 8, 2018 @tpr @kongondo thanks again. but i took a second thought on that. for my purpose it's better the visitor gets a designed pdf having all the images in place instead of getting them as single files to their download folder. so i ended up using the fpdf library … works like a charm.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now