I am using the following script to create zip files: http://davidwalsh.name/create-zip-php
It's working just fine and does exactly what I need. Sometimes though I have large files and zipping those takes up to 30 seconds.
I want to let the user know that their download is being packed and tell them whenever the download is ready.
How would I do that? I have a script which is called download.php which basically just calls this create_zip method from above and then forces a download like this:
$files = explode(":", $file_decrypted);
array_pop($files);
$zipname = 'uploads/download_' . $username . '.zip';
foreach ($files as &$value) {
$value = "uploads/" . $username_d . "/" . $value;
}
$resultat = create_zip($files, $zipname, 'uploads/' . $username . '/');
ob_clean();
ob_end_flush();
// Start the download for the user
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename=' . $zipname);
header('Content-Length: ' . filesize($zipname));
readfile($zipname);
exit();
So basically I want to show a text to the user (For example: Preparing download...) and at the same time call all the above php stuff in the background somehow.
Related
I'm trying to create a zip archive from some files using PHP.
$zipname = 'path/to/my/dir/' . uniqid('MyZip', true) . '.zip';
$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);
foreach ($files as $file) {
$dl_file = file_get_contents($file);
$zip->addFromString(basename($file),$dl_file);
}
$zip->close();
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename=' . $zipname);
header('Content-Length: ' . filesize($zipname));
readfile($zipname);
unlink($zipname);
It creates an archive just fine in the correct location named something to the extent of: MyZip124153.zip
However, the file my browser downloads is named path-to-my-dirMyZip124153.zip.
I'm not sure how I can prevent it from doing this. I'd prefer to not have this filesystem info embedded in these filenames.
Thank you!
Obviously it is going to put the path inside a file name , as you are using the path string as filename inside the header.
Change your :
header('Content-disposition: attachment; filename=' . $zipname);
to something like :
$new_file_name = 'myzipfile.zip';
header('Content-disposition: attachment; filename=' . $new_file_name);
I currently am working on a PHP project that uses the Zend Framework. I am making a CSV without any issues in the controller, but then want the user to be able to download the file by clicking a button in the view.
In my .phtml I have:
<a class="btn" href="<?php echo $this->download;?>" download>Export to CSV</a>
$this->download is being set in the controller:
$view["download"] = $this->_createCSV($bqc_jobs, $startDate, $endDate, $processor_id, $defaultTime);
The _createCSV function creates the CSV and stores it in the temporary directory that the site uses. It then returns the filepath.
private function _createCSV($jobs, $start, $end, $user=null, $minutes){
$format = "Ymd_His";
if(!$start && !$user){
$start = date($format, strtoTime("-" . $minutes . " minutes"));
}
if(!$end){
$end = \DateTime::createFromFormat($format, date($format))->format($format);
}
$directory = Config::$tempDir;
$fileName = $directory . "/" . ($user ? $user . "_" : "") . ($start ? $start . "_" : "") . $end . "_report.csv";
$file = fopen($fileName, 'w');
foreach ($jobs as $job){
fputcsv($file, $job);
}
fclose($file);
return $fileName;
}
When the button is clicked, the browser tries to download the file, but errors because it cannot find the file. This makes sense, since the browser should not have access to the temporary folder, but I'm not entirely sure how to get around this.
If you are unable to see the folder due to the UNIX file permissions, then your only options will be to:
Change the file permissions on the tmp folder so that your web server can read/write there using chmod/chown (I assume it is a linux system?)
Use a different folder with sufficient permissions
Don't store the file on disk - store it in a database instead (not optimal).
Once you are sure your file permissions are in order and that the file can be read by apache, it appears that you should be able to use php's readfile function to actually transmit the file back to the browser:
<?php
$file = '/tmp/monkey.gif';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
?>
I need some eduction please.
At the end of each month, I want to download some data from my webserver to my local PC.
So, I've written a little script for that, which selects the data from the DB.
Next, I want to download it.
I've tried this:
$file=$month . '.txt';
$handle=fopen($file, "w");
header("Content-Type: application/text");
header("Content-Disposition: attachment, filename=" . $month . '.txt');
while ($row=mysql_fetch_array($res))
{
$writestring = $row['data_I_want'] . "\r\n";
fwrite($handle, $writestring);
}
fclose($handle);
If I run this, then the file is created, but my file doesn't contain the data that I want. Instead I get a dump from the HTML-file in my browser..
What am I doing wrong..
Thanks,
Xpoes
Below script will help you download the file created
//Below is where you create particular month's text file
$file=$month . '.txt';
$handle=fopen($file, "w");
while ($row=mysql_fetch_array($res)){
$writestring = $row['data_I_want'] . "\r\n";
fwrite($handle, $writestring);
}
fclose($handle);
//Now the file is ready with data from database
//Add below to download the text file created
$filename = $file; //name of the file
$filepath = $file; //location of the file. I have put $file since your file is create on the same folder where this script is
header("Cache-control: private");
header("Content-type: application/force-download");
header("Content-transfer-encoding: binary\n");
header("Content-disposition: attachment; filename=\"$filename\"");
header("Content-Length: ".filesize($filepath));
readfile($filepath);
exit;
Your current code does not output a file, it just sends headers.
in order for your script to work add the following code after your fclose statement.
$data = file_get_contents($file);
echo $data;
My download.php is not working . After downloading is completed, the error on opening file is 'the archived file is corrupted or damaged '.
I dont know the reason of an error. so please help me. This code was a hard code. i tested this code by giving the name of the images. it worked right but when i retreived the images from database and tried to run this code , something went wrong.
<?php
echo "<br/>" , $product_id=$_REQUEST['product_id'];
echo "<br/>" , $query= ("SELECT image_name FROM " . $db_prefix ."product WHERE image_id = $product_id");
$test = class_exists('ZipArchive');
///$url='upload_images/';
$url = $_SERVER['DOCUMENT_ROOT'].'photohive/upload_images/';
$zip = new ZipArchive;
$zip->open($_SERVER['DOCUMENT_ROOT'].'photohive/downloads/file_' . time() . '.zip', ZipArchive::CREATE);
$result = mysql_query($query);
while( $row= #mysql_fetch_assoc($result))
{
//echo $url. $row['image_name'];
$file_name = $url.$row['image_name'];
if(file_exists($file_name)){
//$zip->addFile($file_name);
//$zip->addFromString(basename($file_name), file_get_contents($file_name));
$zip->addFile(realpath($file_name), $file_name);
}
}
$zip->close();
$encoding = 'binary';
$filename = $_SERVER['DOCUMENT_ROOT'].'photohive/downloads/file_' . time() . '.zip';
header('Pragma: public');
header('Expires: 0');
header('Content-Description: File Transfer');
header('Content-Disposition: filename="' . basename($filename). '"');
header('Content-Type: application/x-zip' );
header('Content-Transfer-Encoding: ' . $encoding);
header('Content-Length: ' . filesize($filename));
$file = readfile($filename);
//print($file);
exit;
?>
In your code you are using this string to get the filename twice: $_SERVER['DOCUMENT_ROOT'].'photohive/downloads/file_' . time() . '.zip';
In the second time, the time() probably will return the different timestamp, as some seconds will pass while you are compress the images.
Also using the time() method will bring the conflict on hi traffic sites, where you could have a possibility to get two or more requests in one second.
I suggest you to use the tempnam() function to generate the file. And remember to delete it after download is completed.
Here is a code:
$filename = tempnam($_SERVER['DOCUMENT_ROOT'].'photohive/downloads', "zip");
...
$zip->open($filename, ZipArchive::OVERWRITE);
And remove this line:
$filename = $_SERVER['DOCUMENT_ROOT'].'photohive/downloads/file_' . time() . '.zip';
after $encoding = 'binary';
I would like to create a form that will allow for custom download assembling, just like the one on jQuery UI download page. The user selects the components s/he needs and a custom download is assembled, (g)zipped and sent out. How does this work? How do I write something similar?
Optionally: since I'd like to implement this on a Drupal 7 site, suggestions for helpful modules are also welcome.
jnpcl's answer works. However, if you want to download the file without requiring a redirect, just do the following:
// Once you created your zip file as say $zipFile, you can output it directly
// like the following
header('Content-Description: File Transfer');
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename='.basename($zipFile));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($zipFile));
ob_clean();
flush();
readfile($zipFile);
http://php.net/manual/en/function.readfile.php
Simple implementation:
<?php
// base directory containing files that we're adding
$dir = 'images/';
// name of our zip file. best to use a unique name here
$zipfile = "test.zip";
// get a directory listing, remove self/parent directories, and reindex array
$files = array_values(array_diff(scandir($dir), array('.', '..')));
// form has been submitted
if (isset($_POST['submit'])) {
// initialize the zip file
$output = new ZipArchive();
$output->open($zipfile, ZIPARCHIVE::CREATE);
// add files to archive
foreach ($_POST['file'] as $num=>$file) {
// make sure the files are valid
if (is_file($dir . $file) && is_readable($dir . $file)) {
// add it to our zip file
$output->addFile($dir . $file);
}
}
// write zip file to filesystem
$output->close();
// direct user's browser to the zip file
header("Location: " . $zipfile);
exit();
} else {
// display filenames with checkboxes
echo '<form method="POST">' . PHP_EOL;
for ($x=0; $x<count($files); $x++) {
echo ' <input type="checkbox" name="file[' . $x . ']" value="' . $files[$x] . '">' . $files[$x] . '<br>' . PHP_EOL;
}
echo ' <input type="submit" name="submit" value="Submit">' . PHP_EOL;
echo '</form>' . PHP_EOL;
}
?>
Known bug: Doesn't check if $zipfile exists beforehand. If it does, it will be appended to.
i dont know anything about that drupal but probably is some help editor for php or similar... however this may help you... PHP ZIP
never used it but it dont seams hard!
hope it helps