I need to be able to open the zip file straight away when we hit the page for download even if the zip file is not created in the server yet.
Is there any way to do this? Because for the moment it takes a lot of time to get the page the start of the download of the zip file.
I'm also getting timeout issue because it takes too much time to build the zip.
$this->loadModel('JobFiles');
$this->loadComponent('Images');
$job_nbr = '40819-o';
$purpose = 'client';
if (isset($this->request->data['type']) && $this->request->data['type'] != '') {
$type = $this->request->data['type'];
$my_files = $this->JobFiles
->find()
->where([
'JobFiles.job_number' => $job_nbr,
'JobFiles.type' => $type,
'JobFiles.purpose' => $purpose
]);
} else {
$my_files = $this->JobFiles
->find()
->where([
'JobFiles.job_number' => $job_nbr,
'JobFiles.purpose' => $purpose
]);
}
$files = array();
$key = 0;
foreach( $my_files as $file ){
// If photo and extension are jpg we provide other files type
if ($file->type == 'photos' && $file->extension == 'jpg' || $file->extension == 'JPG'):
$c = $file->ObjectURL;
$file_headers = #get_headers($c);
if(!$file_headers || $file_headers[0] == 'HTTP/1.1 404 Not Found') {
$exists = false;
}
else {
$files['photos'][$key]['original_file'] = $file->ObjectURL;
$files['photos'][$key]['name'] = $file->filename;
$files['photos'][$key]['type'] = $file->type;
$files['photos'][$key]['id'] = $file->id;
$key++;
}
endif;
if ($file->type == 'floorplan'):
$files['floorplan'][$key]['original_file'] = $file->ObjectURL;
$key++;
endif;
if ($file->type == 'video'):
$files['video'][$key]['original_file'] = $file->ObjectURL;
$key++;
endif;
}
$zipname = "watherver.zip";
$zip = new ZipArchive();
$zip_full_path_name = \Cake\Core\Configure::read('pathTo') . '/webroot/img/tmp/zip/' . $zipname;
$zip->open($zip_full_path_name, ZIPARCHIVE::CREATE);
foreach ($files['photos'] as $file) {
$context = stream_context_create(array('http' => array('header'=>'Connection: close\r\n')));
$parsed_file = $file['original_file'];
$download_file = file_get_contents($parsed_file, false,$context);
$zip->addFromString('photos/original/' . basename($parsed_file), $download_file);
}
$zip->close();
//Set headers
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename='" . $zipName . "'");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($zipName));
Cheers,
Related
I have the following code to force download an IPA file (after codesigning it with a script). It works fine with smaller files but with larger files, my web server starts returning a 500 Internal Server Error. Would someone be able to help me tweak my existing code to overcome this issue?
$time = md5(time());
// Runs code signing script here
// And then attempts to initiate download
$path = "done/$time/";
$latest_ctime = 0;
$latest_filename = '';
$d = dir($path);
while (false !== ($entry = $d->read())) {
$filepath = "{$path}/{$entry}";
if (is_file($filepath) && filectime($filepath) > $latest_ctime) {
$latest_ctime = filectime($filepath);
$latest_filename = $entry;
}
}
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$time.ipa");
header("Content-Type: application/ipa");
header("Content-Transfer-Encoding: binary");
// Read the file from disk
readfile("done/$time/".$latest_filename);
// header('location: dashboard.php');
} else {
// Throwback
die("Failed. Contact support. // <p>$sign</p>");
}
Here is an example:
$filepath = "done/{$time}/{$latest_filename}";
$size = filesize($filepath);
$mimetype = 'application/ipa';
// Turn off buffering
if (ob_get_level()) {
ob_end_clean();
}
$handle = fopen($filepath, 'rb');
if ($handle !== false && $size > 0) {
#flock($handle, LOCK_SH);
$filename = rawurldecode($filepath);
$old_max_execution_time = ini_get('max_execution_time');
$old_cache_limiter = session_cache_limiter();
ini_set('max_execution_time', 0);
session_cache_limiter(false);
header("Cache-Control: public");
header("Content-Description: File Transfer");
header('Content-Type: ' . $mimetype);
header('Content-Transfer-Encoding: binary');
header('Content-disposition: attachment; filename="'. $filename .'"');
// or your variant
// header("Content-Disposition: attachment; filename=" . md5(time()));
header("Content-Length: $size");
$start = 0;
$end = $size - 1;
$chunk = 8 * 1024;
$requested = (float)$end - (float)$start + 1;
while (! $error) {
if ($chunk >= $requested) {
$chunk = (integer)$requested;
}
set_time_limit(0);
while (! feof($handle) && (connection_status() === 0)) {
if (! $buffer = #fread($handle, $chunk)) {
$error = true;
break 2;
}
print($buffer);
flush();
}
#flock($handle, LOCK_UN);
#fclose($handle);
ini_set('max_execution_time', $old_max_execution_time);
session_cache_limiter($old_cache_limiter);
break;
}
if ($error) {
// 500 - Internal server error
exit;
}
} else {
// Can't open file
exit;
}
Maybe problem in script time execution.
Try to set ini_set('max_execution_time', 0);
Also try to read and send file by chunks.
I've been working with this code all day but for some reason files won't get deleted after timer has run out.$zip_file_name is the file that I'd like to see gone after 30secs
$the_folder = '../test';
$zip_file_name = ("PHOENIX_fullbackup_$now.zip");
$download_file= true;
//$delete_file_after_download= true; doesnt work!!
class FlxZipArchive extends ZipArchive {
/** Add a Dir with Files and Subdirs to the archive;;;;; #param string $location Real Location;;;; #param string $name Name in Archive;;; #author Nicolas Heimann;;;; #access private **/
public function addDir($location, $name) {
$this->addEmptyDir($name);
$this->addDirDo($location, $name);
} // EO addDir;
/** Add Files & Dirs to archive;;;; #param string $location Real Location; #param string $name Name in Archive;;;;;; #author Nicolas Heimann
* #access private **/
private function addDirDo($location, $name) {
$name .= '/';
$location .= '/';
// Read all Files in Dir
$dir = opendir ($location);
while ($file = readdir($dir))
{
if ($file == '.' || $file == '..') continue;
// Rekursiv, If dir: FlxZipArchive::addDir(), else ::File();
$do = (filetype( $location . $file) == 'dir') ? 'addDir' : 'addFile';
$this->$do($location . $file, $name . $file);
}
} // EO addDirDo();
}
$za = new FlxZipArchive;
$res = $za->open($zip_file_name, ZipArchive::CREATE);
if($res === TRUE)
{
$za->addDir($the_folder, basename($the_folder));
$za->close();
}
else { echo 'Could not create a zip archive';}
if ($download_file)
{
ob_get_clean();
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=" . basename($zip_file_name) . ";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($zip_file_name));
readfile($zip_file_name);
if ($handle = opendir ($zip_file_name)) {
while (false !== ($file = readdir($handle))) {
if (filectime($file)< (time()-30)) { // timer -30secs
unlink($file);
}
}
}
}
?>
Any help is greatly appreciated.thanks
you could delete zip file (if it already exists) prior to generating the zip file - so that old files are deleted first before new ones are generated:
E.g. (snippet of your code)
<?php
// Delete previous zip files
$old_files = glob($the_folder .'/*.zip');
foreach ($old_files as $old_file) {
unlink($old_file);
}
// Usage
$za = new FlxZipArchive;
$res = $za->open($zip_file_name, ZipArchive::CREATE);
if ($res === TRUE)
{
// Add Files to Zip
$za->addDir($the_folder, basename($the_folder));
$za->close();
// Download If enabled
if ($download_file)
{
ob_get_clean();
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=" . basename($zip_file_name) . ";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($zip_file_name));
readfile($zip_file_name);
}
}
else
{
echo 'Could not create a zip archive';
}
?>
Helo I'm trying to create download script in PHP... Upload form is ok and it stores file in folder 'upload/' but and file name is stored in DB, but when I download, it downloads file e.g. some image, when I want to see image it's only red X like here: image....any ideas?
<?php
include 'connect.php';
$query = "SELECT * FROM topics WHERE topic_id = '". $_GET['topic_id'] ."' ";
$result = mysql_query($query);
$row = mysql_fetch_array($result);
$name = $row['topic_subject'];
$file = $row['topic_file'];
header('Pragma: public');
header('Content-Description: File Transfer');
header("Content-Disposition: attachment; filename='".$file . "'");
header("Content-Type: ".mime_content_type($file)."");
header("Content-Length: " . filesize($file) ." ");
header('Content-Transfer-Encoding: binary');
readfile('uploads/',$file);
ob_clean();
flush();
?>
Looks like the issue could be in your call to readfile. You need to use a . to concatenate the file path to the file name, so replace;
readfile('uploads/',$file);
with
readfile('uploads/'.$file);
I’m using my own script for file download. Its best i find ever. You can also modify it as user requirement.
function download_file($Source_File, $Download_Name, $file_extension = '') {
/*
$Source_File = path to a file to output
$Download_Name = filename that the browser will see
$file_extension = MIME type of the file (Optional)
*/
if (!is_readable($Source_File))
die('File not found or inaccessible!');
$size = filesize($Source_File);
$Download_Name = rawurldecode($Download_Name);
/* Figure out the MIME type (if not specified) */
$known_mime_types = array(
"pdf" => "application/pdf",
"csv" => "application/csv",
"txt" => "text/plain",
"html" => "text/html",
"htm" => "text/html",
"exe" => "application/octet-stream",
"zip" => "application/zip",
"doc" => "application/msword",
"xls" => "application/vnd.ms-excel",
"ppt" => "application/vnd.ms-powerpoint",
"gif" => "image/gif",
"png" => "image/png",
"jpeg" => "image/jpg",
"jpg" => "image/jpg",
"php" => "text/plain"
);
if ($file_extension == '') {
// $file_extension = strtolower(substr(strrchr($Source_File,"."),1));
if (array_key_exists($file_extension, $known_mime_types)) {
$mime_type = $known_mime_types[$file_extension];
} else {
$mime_type = "application/force-download";
};
};
#ob_end_clean(); //off output buffering to decrease Server usage
// if IE, otherwise Content-Disposition ignored
if (ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
header('Content-Type: ' . $mime_type);
header('Content-Disposition: attachment; filename="' . $Download_Name . '"');
header("Content-Transfer-Encoding: binary");
header('Accept-Ranges: bytes');
header("Cache-control: private");
header('Pragma: private');
header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + 3600));
// multipart-download and download resuming support
if (isset($_SERVER['HTTP_RANGE'])) {
list($a, $range) = explode("=", $_SERVER['HTTP_RANGE'], 2);
list($range) = explode(",", $range, 2);
list($range, $range_end) = explode("-", $range);
$range = intval($range);
if (!$range_end) {
$range_end = $size - 1;
} else {
$range_end = intval($range_end);
}
$new_length = $range_end - $range + 1;
header("HTTP/1.1 206 Partial Content");
header("Content-Length: $new_length");
header("Content-Range: bytes $range-$range_end/$size");
} else {
$new_length = $size;
header("Content-Length: " . $size);
}
/* output the file itself */
$chunksize = 1 * (1024 * 1024); //you may want to change this
$bytes_send = 0;
if ($Source_File = fopen($Source_File, 'r')) {
if (isset($_SERVER['HTTP_RANGE']))
fseek($Source_File, $range);
while (!feof($Source_File) &&
(!connection_aborted()) &&
($bytes_send < $new_length)
) {
$buffer = fread($Source_File, $chunksize);
print($buffer); //echo($buffer); // is also possible
flush();
$bytes_send += strlen($buffer);
}
fclose($Source_File);
} else
die('Error - can not open file.');
die(1); // A response code other than 0 is a failure
}
I hope this will help you.
Cheers!
Mudassar Ali
You have to give the full path of an image to the readfile() function.
Following is my code to download zip file using PHP.
function create_zip($files, $file_name, $overwrite = false) {
foreach ($files as $imglink) {
$img = file_get_contents($imglink);
$destination_path = $_SERVER['DOCUMENT_ROOT'] . 'demoproject/downloads/' . time() . '.jpg';
file_put_contents($destination_path, $img);
$imgFiles[] = $destination_path;
}
if (file_exists($file_name) && !$overwrite) {
return false;
}
$valid_files = array();
if (is_array($imgFiles)) {
foreach ($imgFiles as $file) {
$valid_files[] = $file;
}
}
if (count($valid_files)) {
$zip = new ZipArchive();
if ($zip->open($file_name, $overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
echo "Sorry ZIP creation failed at this time";
}
foreach ($valid_files as $file) {
$zip->addFile($file, pathinfo($file, PATHINFO_BASENAME));
}
$count = $zip->numFiles;
$resultArr = array();
$resultArr['count'] = $count;
$resultArr['destination'] = $file_name;
$filename = $file_name;
$filepath = $_SERVER['DOCUMENT_ROOT'] . 'demoproject/';
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"" . $filename . "\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($filepath . $filename));
ob_end_flush();
#readfile($filepath . $filename);
} else {
return false;
}
}
Here the $filename and $filepath containing the name and path of zip file respectively.
Ex:
echo $filepath.$filename;
Output : D:/wamp/www/demoproject/1357198557.zip
The issue is it displaying download window but showing the folder size 0 byte. I am using windows7. See image below :
Can you try adding this, Make sure you got proper filesize
$mm_type="application/octet-stream";
header("Content-Type: " . $mm_type);
header("Content-Length: " .(string)(filesize($fullpath)) );
I am trying to read and get the size of the zip file in PHP.
Following is my code:
function create_zip($files, $file_name, $overwrite = false) {
foreach ($files as $imglink) {
$img = file_get_contents($imglink);
$destination_path = $_SERVER['DOCUMENT_ROOT'] . 'demoproject/downloads/' . time() . '.jpg';
file_put_contents($destination_path, $img);
$imgFiles[] = $destination_path;
}
if (file_exists($file_name) && !$overwrite) {
return false;
}
$valid_files = array();
if (is_array($imgFiles)) {
foreach ($imgFiles as $file) {
$valid_files[] = $file;
}
}
if (count($valid_files)) {
$zip = new ZipArchive();
if ($zip->open($file_name, $overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
echo "Sorry ZIP creation failed at this time";
}
foreach ($valid_files as $file) {
$zip->addFile($file, pathinfo($file, PATHINFO_BASENAME));
}
$count = $zip->numFiles;
$resultArr = array();
$resultArr['count'] = $count;
$resultArr['destination'] = $file_name;
$filename = $file_name;
$filepath = $_SERVER['DOCUMENT_ROOT'] . 'demoproject/';
$fileSize = filesize($filepath . $filename) / 1024;
echo 'size of the file is : ' . $fileSize . ' kb';
exit;
// $size = 0;
// $resource = zip_open($filepath . $filename);
// while ($dir_resource = zip_read($resource)) {
// $size += zip_entry_filesize($dir_resource);
// }
header("Pragma: no-cache");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"" . $filename . "\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . zip_entry_filesize($filepath . $filename));
if (#readfile($filepath . $filename) === false) {
header('http://localhost/demoproject/fbindex.php');
return 500;
} else {
header('Location:http://localhost/demoproject/fbindex.php');
return 200;
}
} else {
return false;
}
}
$files : contain the array of images and
$file_name : contain name of file : that is : $file_name = time() . ".zip";
In the above code $filename contains the actual zip file and $filepath contains the location of the zip file.
The issue is it's reading the file but always showing its size 0 instead of actual file size.
This is I am doing :
echo $size;
O/P : 0
Where am I going wrong? Need Help. Thanks
try this -
$fileSize = filesize($filepath . $filename)/1024;
echo 'size of the file is : '.$fileSize.' kb';
Shouldn't you close ZIP file just after adding files to it?
$zip->close();
Try clearstatcache() just before calling filesize().
Closing your zip file before all this is also a great idea.
I know I'm a bit late on this, but who knows?