I am trying to download large zip files (800MB to 1GB) containing audio files to the browser. As I have seen so far, chunking seems to be the most popular approach, but I am having zero luck. The code I have been working with is
$filename = $_SERVER['DOCUMENT_ROOT'] . $filepath;
$download_rate = 5000;
$progress = 0;
if (file_exists($filename)) {
header('Cache-control: private');
header('Content-Type: application/octet-stream');
header('Content-Length: '.filesize($filename));
header('Content-Disposition: filename='.basename($filename));
flush();
$file = fopen($filename, "r");
while(!feof($file)) {
// send the current file part to the browser
print fread($file, round($download_rate * 1024));
// flush the content to the browser
flush();
// sleep one second
sleep(1);
}
fclose($file);
} else echo 'File does not exist!';
This works for a wide variety of file types and sizes up to a certain point -- I have no problem downloading typical PDFs, etc. But the browser just spins and spins when I try to download large zip files, and eventually dies (around 2 minutes). I am really needing some help here. I've tried a number of code variants for chucking, but something always seems to die and I'm not sure what I'm doing wrong. Perhaps there's a better approach to chunking?
Consider change change for readfile will not present any memory issues, your lost download rate and progress show in browser. your limit download rate in .httaccess.
$filename = $_SERVER['DOCUMENT_ROOT'] . $filepath;
if (file_exists($filename)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($filename).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: '.filesize($filename));
readfile($filename);
} else echo 'File does not exist!';
https://www.php.net/manual/en/function.readfile.php
Related
While writing a PHP-Script, im stuck at an issue i cant resolve.
The PHP-Script consist in letting a user download a .mp4 file. The download works without any issues but the file downloaded can not be played.
Heres the code:
<?php
$filepath = "/www/servermedia/technounion.mp4";
$filename = basename($filepath);
header("Content-type: video/mp4");
header("Content-Disposition: attachment; filename=.$filename");
readfile($filename);
exit;
?>
After the .mp4 file gets downloaded, it cannot be played.
It looks like this:
The error message means that Windows Media Player cannot play back the file because probably the player doesnt support the codec. I already tried with VLC but it does not work either.
EDIT:
Comparing both file sizes, the downloaded file is only a couple bytes large instead of the 3,73 MB of the file on the server
Your code is not well-formed, you miss to escape double-quotes by adding single-quotes as I done here, please test my answer.
<?php
$filepath = "/www/servermedia/technounion.mp4";
$filename = basename($filepath);
header('Content-Type: video/mp4');
header('Content-Disposition: attachment; filename="' . $filename . '"');
readfile($filename);
exit;
?>
But I suggest a more complex way:
<?php
$filepath = $_SERVER['DOCUMENT_ROOT'] . "/www/servermedia/technounion.mp4";
$filename = basename($filepath);
header('Content-Type: video/mp4');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . sprintf("%u", filesize($filepath)));
set_time_limit(0);
$fh = fopen($filepath, "rb");
while (!feof($fh)) {
echo fgets($fh);
ob_flush();
flush();
}
fclose($fh);
exit;
?>
$_SERVER['DOCUMENT_ROOT'] is useful to get the full path from the server
set_time_limit(0) is useful to avoid any timeout during download
fgets() is useful for reading large files
ob_flush() and flush() assure that there is not other output in the buffer
I hope this helps.
Is the downloaded file the exact same filesize?
Does the content type exist in your webserver?
header("Content-Type: video/mp4"); Note capital 'T' for type.
This maybe worth testing with to see you can serve the file content inline:
http://www.phpmind.com/blog/2016/10/how-to-use-php-to-output-an-mp4-video/
i have website for storing large zip file and upload it to ftp server in php
now i want to download the file from ftp and limiting download speed
and be able to resuming and pause download i have this code :
$file_path = 'ftp://'.$ftp_username.':'.$ftp_password.'#'.$ftp_server.'/'.$ftp_filename_withDiR ;
$filesize_ftp = filesize($file_path);
ob_clean();
$download_rate = $Mbspeed;
header('Content-Description: File Transfer');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Type: application/octet-stream');
header("Content-Length:".$filesize_ftp);
header('Content-Disposition: filename='.$filenamea);
flush();
$file = fopen($file_path, "r");
while(!feof($file)) {echo fread($file, round($download_rate * 1024));flush();usleep(200); }
But i can't pause the download ! any ideas to solve this problem?
I have gone through all articles on Stack Overflow and can't fix my issue. I am using following code:
$file = $_GET['url'];
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
The above mention code is downloading the file from the directly above the root and Yes it is downloading a PDF file but the file is only of 1KB size and not the original size. The $_GET['url'] is receiving ../dir/dir/filename.pdf in it. the filename is space in it as well. For security reason I cannot share the file name.
Please let me know where am I going wrong.
Please make sure you are using the web server path to access the file - for instance your path could be: /home/yourusername/public/sitename/downloads/<filename>, you should check first - to help you can run this at the top of your PHP script to find out the full path for the current script:
echo '<pre>FILE PATH: '.print_r(__FILE__, true).'</pre>';
die();
Only send the filename with the url using urlencode() and on the receiving PHP script use urldecode() to handle any character encoding issues.
See here: http://php.net/manual/en/function.urlencode.php
and here: http://php.net/manual/en/function.urldecode.php
So where you create your url:
Download File
And in your php script:
$file_base_path = '/home/yourusername/public/sitename/downloads/';
$file = urldecode($_GET['url']);
$file = $file_base_path . $file;
$file = $_GET['url'];
if (file_exists($file))
{
if (FALSE!== ($handler = fopen($file, 'r')))
{
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: chunked'); //changed to chunked
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
//header('Content-Length: ' . filesize($file)); //Remove
//Send the content in chunks
while(false !== ($chunk = fread($handler,4096)))
{
echo $chunk;
}
}
exit;
}
echo "<h1>Content error</h1><p>The file does not exist!</p>";
I hope this helps you!
In the website page contains many images with downloading options. If I click the download button it automatically downloaded on user system and it shows on browser downloadable page. I have PHP code like
$image = file_get_contents('http://website.com/images/logo.png');
file_put_contents('C:/Users/ASUS/Downloads/image.jpg', $image);
Above coding is working fine. But I need to provide the path name for image to save. In user side we don`t know the path.
I need the PHP code to use the browser download location and download images need to show the browser downloads.
not possible to store the image in particular user location due to security issues .you don't force user .you have to suggest him to store particular location .and also you don't know the what file system there in user system.and also downloading path can be setting up by user anywhere so your not able to get that.
$filename = '/images/'.basename($_POST['text']);
file_put_contents($filename, $content);
you have to save/download the image somewhere on your web serwer and next send the file to user using header function, for example:
$file = 'path_to_image';
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;
}
else {
echo "file not exists";
}
manual
`<?php
$filename ='http://website.com/images/logo.png';
$size = #getimagesize($filename);
$fp = #fopen($filename, "rb");
if ($size && $fp)
{
header("Content-type: {$size['mime']}");
header("Content-Length: " . filesize($filename));
header("Content-Disposition: attachment; filename=$filename");
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
fpassthru($fp);
exit;
}
header("HTTP/1.0 404 Not Found");
?>`
I am having some major problems when with a script I have to download files from S3.
The problem I'm encountering is that every time I try to download a file, the download starts perfectly, but about halfway through a download the file just stops. Every time. On every file. These are video files, so a lot of them are significantly big. Not sure what to do or how to approach this. Here's my script:
<?php
// other code exists; this is the main download logic
set_time_limit(0);
ignore_user_abort(false);
ini_set('output_buffering', 0);
ini_set('zlib.output_compression', 0);
$chunk = 10 * 1024 * 1024; // bytes per chunk (10 MB)
$fh = fopen($video->getMp4Source(), "rb");
if ($fh === false) {
echo "Unable open file";
}
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Expires: 0');
header('Pragma: public');
header('Content-Description: File Transfer');
header('Content-type: MP4');
header('Content-length: ' . $video->getFileSize());
header('Content-Disposition: attachment; filename="'.$video->getMp4Source().'"');
while (!feof($fh)) {
echo fread($fh, $chunk);
ob_flush(); // flush output
flush();
}
exit;
I'm not sure what is wrong, or why it keeps happening. There are no errors being logged, and no errors are occurring outside from the file failing to complete its download. I have tried this with readfile(), but it was using up too many resources and it wasn't completing, regardless.
Any help would be great.