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();
}
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 hotlink prevention to the following code only to be accessed by *.mydomain.com via php? Where do I add it?
<?php
$dir = 'folder';
$file = $_GET['name'];
// local file that should be send to the client
$local_file = $dir.'/'.$file;
// filename that the user gets as default
$download_file = 'video.mp4';
// set the download rate limit (=> 20,5 kb/s)
$download_rate = 200;
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: File '.$local_file.' does not exist!');
}
?>
I know it must be something like
define('HOTLINK_PROTECTION',TRUE); // enable hotlinking? true/false
define('HOTLINK_PAGE_URL','http://www.mydomain.com/images/hotlink.jpg'); // Hotlink URL
$allowed_domains="*.mydomain.com, www.mydomain.com";
#checks the referer of the script
function getReferer() { preg_match('#^(?:http://)?([^/]+)#i',$_SERVER['HTTP_REFERER'], $match); return $match[1]; }
#checks if referer domain is okay
function hotlink_check() {
global $allowed_domains; $allowed_domains.=','.$_SERVER['HTTP_HOST'];
$domains=explode(',',str_replace(' ','',$allowed_domains));
$referer=getReferer(); $site=array();
foreach ($domains as $value) { $site[]='^'.str_replace('*','([0-9a-zA-Z]|\-|\_)+',str_replace('.','\.',$value)).'$'; }
foreach ($site as $pattern) { if(eregi($pattern,$referer)) $MATCH=TRUE; if($MATCH==TRUE) break; }
if($MATCH==TRUE) return TRUE; else return FALSE;
}
define('HOTLINK_PASS',hotlink_check());
if(HOTLINK_PROTECTION&&!HOTLINK_PASS&&$_SERVER['QUERY_STRING']!='admin') { header('HTTP/1.1 403 Forbidden'); header('Location: '.HOTLINK_PAGE_URL); die(); }
But where do I implement it? How can I do that?
--- Edit ---
I did it, but it doensn't work with Mozilla Firefox... With firefox it just goes directly to the hotlink image.
I've tested it with Chrome, Internet Explorer, Safari and Opera and the only one who took me to the hotlinked image was Firefox, I must be doing something wrong here.
Here's the code:
<?php
define('HOTLINK_PROTECTION',TRUE); // enable hotlinking? true/false
define('HOTLINK_PAGE_URL','http://www.site.com/images/hotlink.jpg'); // Hotlink URL
$allowed_domains="*.site.com, www.site.com";
#checks the referer of the script
function getReferer() { preg_match('#^(?:http://)?([^/]+)#i',$_SERVER['HTTP_REFERER'], $match); return $match[1]; }
#checks if referer domain is okay
function hotlink_check() {
global $allowed_domains; $allowed_domains.=','.$_SERVER['HTTP_HOST'];
$domains=explode(',',str_replace(' ','',$allowed_domains));
$referer=getReferer(); $site=array();
foreach ($domains as $value) { $site[]='^'.str_replace('*','([0-9a-zA-Z]|\-|\_)+',str_replace('.','\.',$value)).'$'; }
foreach ($site as $pattern) { if(eregi($pattern,$referer)) $MATCH=TRUE; if($MATCH==TRUE) break; }
if($MATCH==TRUE) return TRUE; else return FALSE;
}
define('HOTLINK_PASS',hotlink_check());
if(HOTLINK_PROTECTION&&!HOTLINK_PASS) { header('HTTP/1.1 403 Forbidden'); header('Location: '.HOTLINK_PAGE_URL); die(); }
$dir = 'directory';
$video = $_GET['name'];
// local file that should be send to the client
$local_file = $dir.'/'.$video;
// filename that the user gets as default
$download_file = 'video.mp4';
// set the download rate limit (=> 200 kb/s)
$download_rate = 200;
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
set_time_limit(0);
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: File '.$local_file.' does not exist!');
}
?>
I had the same problem
it was that I used my entire domain name in the file url instead of a relative path..
//download image now
$file_name = "test.jpg";//$_GET['f'];
$file_url = "http://www.example.com/yfolder/". $file_name; //WRONG
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header('Content-Type: image/jpg');
header("Content-disposition: attachment; filename=\"".$file_name."\"");
readfile($file_url);
correct code
//download image now
$file_name = "test.jpg";//$_GET['f'];
$file_url = "yfolder/". $file_name; //i removed my domain and it worked, i managed to download the actual image instead of the hotlinked image
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header('Content-Type: image/jpg');
header("Content-disposition: attachment; filename=\"".$file_name."\"");
readfile($file_url);
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/
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();