php download limit zip damage when set file size - php

Zip damaged after set file size header
I have this code to limit download speed in php :
function readfile_chunked($filename, $retbytes = TRUE) {
$download_rate = 85; global $filename ;
// send headers
header('Cache-control: private');
header('Content-Type: application/octet-stream');
header('Content-Length: '.filesize($filename));
header('Content-Disposition: filename=file.zip');
// flush content
flush();
// open file stream
$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
usleep(200);
}
}
When i set header for content length like this:
header('Content-Length: '.filesize($filename));
and open the downloaded file show me an alert that file is damaged . Not just the zip files i try on jpg file and its the same .
BUT WHEN I REMOVE THE FILE SIZE HEADER THE FILE OR IMAGE OPEN WITHOUT ANY ERROR

I #solved the problem by adding ob_clean() in the begin of function. I was trying to solve it for 3 months This need a party ;)
function party(forVisitors){
Drink();
Play();
HaveFun();
GoHome();
}

Related

PHP - download a CSV file but Firefox browser detects it as Zip file

when i download a CSV file on Firefox browser then detect it is Zip file (must be CSV)
I want to it is CSV file.
this is my the code
<?php
$filename = 'example.csv';
header('Cache-Control: public');
header('Pragma: public');
header('Content-Type: application/csv; name="' . $filename. '"');
header("Content-Disposition: attachment; filename*=UTF-8''" . rawurlencode($filename));
$th = array();
$th[] = "名前";
mb_convert_variables('SJIS','UTF-8',$th);
$out = fopen('php://output', 'w');
fputcsv($out, $th);
fclose($out);
ob_get_contents();
ob_flush();
flush();
According to RFC7111, the correct MIME type for CSV file is "text/csv". Also, you don't usually need to flush the output buffer.
To give browser full information, you can try writing the CSV into buffer, calculate the buffer size for content-length, then output the buffer content.
If your file encoding is in UTF-8, this should be sufficient:
<?php
// Use output buffer to prevent any warning or error from
// polluting the CSV output.
ob_start();
// CSV contents
$data = [
['名前', '電話番号'],
['David', '12345678'],
['John', '23456789'],
];
// write to buffer
$buffer = fopen('php://temp', 'w');
foreach ($data as $row) {
fputcsv($buffer, $row);
}
rewind($buffer);
$size = fstat($buffer)['size'] ?? 0;
// drop the output buffer content
// leave the $buffer content (CSV body) alone
ob_end_clean();
// Send HTTP header and content
// for the CSV response.
$filename = 'example.csv';
header('Cache-Control: public');
header('Pragma: public');
header('Content-Type: text/csv; name="' . $filename. '"');
header('Content-Length: ' . $size);
header("Content-Disposition: attachment; filename*=UTF-8''" . rawurlencode($filename));
echo stream_get_contents($buffer);
References:
I/O Streams
"php://" stream wrapper
exit();
When I add the above command at the end of the file code, then it works normally again.
But I don't understand yet why adding exit() has this working properly
This "error" is related to your computer file open configuration. Maybe you checked the option to assign .csv files to this zip software, but, is easy to change the software and set another one.

Download speed limit script doesn't work

I've find a script here which permit to limit the download speed of a file.
// The file that will be sent to the user
$your_file = 'file.zip';
// Rename the file name
$new_file = 'new-filename.zip';
// Set the download speed limit (70 kb/s)
$download_speed = 70;
if(file_exists($myl_file) && is_file($my_file)) {
// Headers
header('Cache-control: private');
header('Content-Type: application/octet-stream');
header('Content-Length: '.filesize($my_file));
header('Content-Disposition: filename='.$new_file);
// Flush the content
flush();
// File stream
$file = fopen($my_file, "r");
while (!feof($file)) {
// Send the current part of the file to the browser
echo fread($file, round($download_speed* 1024));
// Flush the content to the browser
flush();
// Sleep one second
sleep(1);
}
// Close file stream
fclose($file);
}
else {
die('Error: The file '.$my_file.' does not exist!');
}
The problem is that the speed limit doesn't works (but I can download the file) I'm always between 1500-2000 kb/s when I change the $download_speed value. I've test it on wamp and on a webserver but impossible to make it work. Any ideas? Thanks you.

How can I add a download speed limit to this php script?

I found this great script to download and protect the files from a directory:
http://www.gowondesigns.com/?page.getfile
And I saw this code from a website too:
// local file that should be send to the client
$local_file = 'test-file.zip';
// filename that the user gets as default
$download_file = 'your-download-name.zip';
// set the download rate limit (=> 20,5 kb/s)
$download_rate = 20.5;
if(file_exists($local_file) && is_file($local_file)) {
// send headers
header('Cache-control: private');
header('Content-Type: application/octet-stream');
header('Content-Length: '.filesize($local_file));
header('Content-Disposition: filename='.$download_file);
// flush content
flush();
// open file stream
$file = fopen($local_file, "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);
}
// close file stream
fclose($file);
}
else {
die('Error: The file '.$local_file.' does not exist!');
}
How can I combine them? I mean how can I use the getfile script and add a download rate to it?
I tried adding:
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);
}
But instead of $file I think it should be $fd and I had no positive results
What am I doing wrong?
Based on your comment - I assume you want the following:
// open file stream
$file = fopen($local_file, "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);
}
// close file stream
fclose($file);
You should note, however, that it is the whole script that will make it successfully prompt a user to download the file and speed limit it. Simply rename the first script in your question as download.php, then link to it as <a href='download.php?id=1'>Download 1</a> (then file ID 1 will download).
<?php
$file_id = $_GET['id'];
if($file_id == 1){
// local file that should be send to the client
$local_file = 'test-file.zip';
// filename that the user gets as default
$download_file = 'your-download-name.zip';
} else {
die('Invalid file selected for download');
}
// set the download rate limit (=> 20,5 kb/s)
$download_rate = 20.5;
if(file_exists($local_file) && is_file($local_file)) {
// send headers
header('Cache-control: private');
header('Content-Type: application/octet-stream');
header('Content-Length: '.filesize($local_file));
header('Content-Disposition: filename='.$download_file);
// flush content
flush();
// open file stream
$file = fopen($local_file, "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);
}
// close file stream
fclose($file);
} else {
die('Error: The file '.$local_file.' does not exist!');
}
?>
<?php
$file = #$_GET["file"];
$rate = 100; // kb/sn
if (!file_exists($file)) {die("File Not Found");}
header("Content-Disposition: attachment; filename=" . $file);
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");
header("Content-Length: " . filesize($file));
flush(); // this doesn't really matter.
$fp = fopen($file, "r");
while (!feof($fp))
{
echo fread($fp, $rate * 1024);
flush();
sleep(1);
}
fclose($fp);
?>
i use this . And no problem.

How to support IDM without allow request the page two times

I got this error ,as the above image show, while trying to download a file by IDM from my site. the limit of requesting this page one time only after entering Captcha Code and if you request the page again must enter the captcha code again.
How to support IDM in this case
The download code as the following
$file='test.mp3';
$download_rate = 50; //50 kb/s
if(file_exists($file) && is_file($file))
{
header('Cache-control: private');
header('Content-Type: application/octet-stream');
header('Content-Length: '.filesize($file));
header('Content-Disposition: filename='.$file);
flush();
$file = fopen($file, "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 Not Found';
}
Use xsendfile. A mod for apache
https://tn123.org/mod_xsendfile/

Unable to browse the site while downloading a file using php

I used this code for downloading files
$file='test.mp3';
$download_rate = 50; //50 kb/s
if(file_exists($file) && is_file($file))
{
header('Cache-control: private');
header('Content-Type: application/octet-stream');
header('Content-Length: '.filesize($file));
header('Content-Disposition: filename='.$file);
flush();
$file = fopen($file, "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 Not Found';
}
but while downloading the file cannot browse the site till the download completed. this happened with IE and Firefox
Any answers?
Only time I know this happens is when you have sessions which have not been written.
I can't see any sessions here so I'm not sure what is causing it.
However, most php download file scripts are used to check for logins so I'm guessing this is the case.
if you do have sessions, try session_write_close();

Categories