sww Posted April 7, 2018 Share 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; ?> Link to comment Share on other sites More sharing options...
tpr Posted April 7, 2018 Share Posted April 7, 2018 My guess is that you would need to supply full absolute paths instead relative ones. 2 Link to comment Share on other sites More sharing options...
kongondo Posted April 8, 2018 Share 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 Link to comment Share on other sites More sharing options...
sww Posted April 8, 2018 Author Share 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. Link to comment Share on other sites More sharing options...
sww Posted April 8, 2018 Author Share 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. Link to comment Share on other sites More sharing options...
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