I have an excel file which can be downloaded..for example NAME.xlsx well it works in firefox but in webkit(safari/chrome) it appends to the name also the extension .xhtml so then name it will be NAME.xlsx.html it should be ONLY .xlsx
Here you have my headers:
$objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel);
$objWriter->save($root.'/application/to_excel/KSW.xlsx');
$this->getResponse()->setHeader('Content-type', 'application/download', true);
$this->getResponse()->setHeader('Content-type', 'application/octet-stream', true);
$this->getResponse()->setHeader('Content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', true);
$this->getResponse()->setHeader('Content-disposition', 'attachment;filename='.basename($root.'/application/to_excel/KSW.xlsx').'', true);
$this->getResponse()->setHeader('Cache-Control', 'max-age=0', true);
So what I'm doing wrong?
I've not had this function fail yet -- it works with all the Office 2007/2010 files that I've tried so far in Safari (Windows) and Chrome. The get_known_mime_types() function just returns a giant array of all the mime-types that my app supports -- just Google for the MIME types you need. $file is the actual path to the file on your host, and $name is the file name that displays in the download (run/save) dialog. I've also given due credit to the place I got most of it from. Hope you have luck with it too:
function file_download($file, $name, $mime_type='') {
/* The majority of this code was taken from:
* http://w-shadow.com/blog/2007/08/12/how-to-force-file-download-with-php/
*
* So a big thanks to them.
* I have modified parts of it, though, so it's not 100% borrowed.
*/
if(!is_readable($file)) die('File not found or inaccessible!');
$size = filesize($file);
$name = rawurldecode($name);
/* Figure out the MIME type (if not specified) */
$known_mime_types = get_known_mime_types();
if($mime_type==''){
$file_extension = strtolower(substr(strrchr($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(); //turn off output buffering to decrease cpu usage
// required for IE, otherwise Content-Disposition may be ignored
if(ini_get('zlib.output_compression')) {
ini_set('zlib.output_compression', 'Off');
}
header('Content-Type: ' . $mime_type);
header('Content-Disposition: attachment; filename="'.$name.'"');
header("Content-Transfer-Encoding: binary");
header('Accept-Ranges: bytes');
/* The three lines below basically make the download non-cacheable */
header("Cache-control: private");
header('Pragma: private');
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
// 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); // 1MB, can be tweaked if needed
$bytes_send = 0;
if ($file = fopen($file, 'r')) {
if(isset($_SERVER['HTTP_RANGE'])) {
fseek($file, $range);
}
while(!feof($file) && (!connection_aborted()) && ($bytes_send<$new_length)) {
$buffer = fread($file, $chunksize);
print($buffer); //echo($buffer); // is also possible
flush();
$bytes_send += strlen($buffer);
}
fclose($file);
} else {
die('Error - can not open file.');
}
die();
}
Related
I'm using a PHP script to control access to download files. This works fine for anything under 2Gb but fails for larger files.
Apache and PHP are both 64bit
Apache will allow the file to be downloaded if accessed directly (which I can't allow)
The guts of the PHP (ignoring the access control):
if (ob_get_level()) ob_end_clean();
error_log('FILETEST: '.$path.' : '.filesize($path));
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($path));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($path));
readfile($path);
exit;
The error log shows the file size fine
[Tue Apr 08 11:01:16 2014] [error] [client *.*.*.*] FILETEST: /downloads/file.name : 2251373807, referer: http://myurl/files/
But the access log has a negative size:
*.*.*.* - - [08/Apr/2014:11:01:16 +0100] "GET /files/file.name HTTP/1.1" 200 -2043593489 "http://myurl/files/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0"
And so browsers refuse to download the file. In fact, using wget, it's not sending anything:
$ wget -S -O - http://myurl/files/file.name
--2014-04-08 11:33:38-- http://myurl/files/file.name
HTTP request sent, awaiting response... No data received.
Retrying.
Try to read the file in chunks and expose them to the browser instead of filling your local memory with 2GB and flushing all at once.
Replace readfile($path); by:
#ob_end_flush();
flush();
$fileDescriptor = fopen($file, 'rb');
while ($chunk = fread($fileDescriptor, 8192)) {
echo $chunk;
#ob_end_flush();
flush();
}
fclose($fileDescriptor);
exit;
8192 bytes is a critical point in some cases, refere to php.net/fread.
Adding some microtime variables (and comparing with the pointer position of the file descriptor) will also allow you to controll the maximum speed of the download.
*(Flushing the output buffer also slightly depends on the webserver, use those commands to be sure it at least tries to flush as much as possible.)
Add code before readfile($path);
ob_clean();
flush();
I use this code for download:
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
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($file));
ob_clean();
flush();
readfile($file);
exit;
}
Your best choice is to force apache to http chunked mode with a function like this. You'll save a lot of PHP memory this way.
function readfile_chunked($filename, $retbytes = TRUE) {
$CHUNK_SIZE=1024*1024;
$buffer = '';
$cnt =0;
$handle = fopen($filename, 'rb');
if ($handle === false) {
return false;
}
while (!feof($handle)) {
$buffer = fread($handle, $CHUNK_SIZE);
echo $buffer;
#ob_flush();
flush();
if ($retbytes) {
$cnt += strlen($buffer);
}
}
$status = fclose($handle);
if ($retbytes && $status) {
return $cnt; // return num. bytes delivered like readfile() does.
}
return $status;
}
I came across this issue before and used the below script for downloading files, it breaks the file into chunks to download large files instead of trying to take the whole file at once. This script also takes into account the browser being used as some browsers (namely IE) can handle headers slightly differently.
private function outputFile($file, $name, $mime_type='') {
$fileChunkSize = 1024*30;
if(!is_readable($file)) die('File not found or inaccessible!');
$size = filesize($file);
$name = rawurldecode($name);
$known_mime_types=array(
"pdf" => "application/pdf",
"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($mime_type=='')
{
$file_extension = strtolower(substr(strrchr($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();
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
header('Content-Type: ' . $mime_type);
header('Content-Disposition: attachment; filename="'.$name.'"');
header("Content-Transfer-Encoding: binary");
header('Accept-Ranges: bytes');
header("Cache-control: private");
header('Pragma: private');
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
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);
}
$chunksize = 1*($fileChunkSize);
$bytes_send = 0;
if ($file = fopen($file, 'r'))
{
if(isset($_SERVER['HTTP_RANGE']))
fseek($file, $range);
while(!feof($file) &&
(!connection_aborted()) &&
($bytes_send<$new_length)
)
{
$buffer = fread($file, $chunksize);
print($buffer);
flush();
$bytes_send += strlen($buffer);
}
fclose($file);
}
else die('Error - can not open file.');
die();
}
My code is this in php file for downloading any file but resume capability showing unknown plz can u suggest me the code for that functionality
its my php page to download a file, have to change code or what to do for changing resume capability in idm ?
if(!isset($_SESSION['user_id'])){
header('location:../index.php');}
$uname=$_SESSION['uname'];
$uid= $_SESSION['user_id'];
function output_file($file, $name, $mime_type='')
{
/*
This function takes a path to a file to output ($file), the filename that the browser will see ($name) and the MIME type of the file ($mime_type, optional).
*/
//Check the file premission
//if(!is_readable($file)) die('File not found or inaccessible!');
$size = filesize($file);
$name = rawurldecode($name);
/* Figure out the MIME type | Check in array */
$known_mime_types=array(
"pdf" => "application/pdf",
"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($mime_type==''){
$file_extension = strtolower(substr(strrchr($file,"."),1));
if(array_key_exists($file_extension, $known_mime_types)){
$mime_type=$known_mime_types[$file_extension];
} else {
$mime_type="application/force-download";
};
};
//turn off output buffering to decrease cpu usage
#ob_end_clean();
// required for IE, otherwise Content-Disposition may be ignored
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
header('Content-Type: ' . $mime_type);
header('Content-Disposition: attachment; filename="'.$name.'"');
header("Content-Transfer-Encoding: binary");
header('Accept-Ranges: bytes');
header('Content-Length: 2052595');
header('Content-Range: bytes 339843-2392437/2392438');
/* The three lines below basically make the
download non-cacheable */
header("Cache-control: private");
header('Pragma: private');
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
// 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);
}
/* Will output the file itself */
$chunksize = 3*(1024*1024); //you may want to change this
$bytes_send = 0;
if ($file = fopen($file, 'r'))
{
if(isset($_SERVER['HTTP_RANGE']))
fseek($file, $range);
while(!feof($file) &&
(!connection_aborted()) &&
($bytes_send<$new_length)
)
{
$buffer = fread($file, $chunksize);
print($buffer); //echo($buffer); // can also possible
flush();
$bytes_send += strlen($buffer);
}
fclose($file);
} else
//If no permissiion
die('Error - can not open file.');
//die
die();
}
//Set the time out
set_time_limit(0);
$temp = explode("\\", $_REQUEST['filename']);
//path to the file
$file_path=$_REQUEST['filename'];
//Call the download function with file path,file name and file type
output_file($file_path, ''.$temp[3].'', 'text/plain');
?>
<?php
$uname=$_COOKIE["uname"];
//echo $uname;
$file=$_REQUEST['filename'];
$file_name="E:\\upload\\$uname\\$file";
$fid=$_REQUEST['fid'];
$con=mysql_connect("localhost","root","Net#123");
$db=mysql_select_db("file_storage",$con);
$query1=mysql_query("SELECT * FROM upload WHERE file_id=$fid");
$row1=mysql_fetch_array($query1);
if($row1)
{
$file_db=$row1['name'];
// If the requested file is exist
if(file_exists($file_name)){
// Get the file size
$file_size=filesize($file_name);
// Open the file
$fh=fopen($file_name, "r");
// Download speed in KB/s
$speed=1024;
//Initialize the range of bytes to be transferred
$start=0;
$end=$file_size-1;
//Check HTTP_RANGE variable
if(isset($_SERVER['HTTP_RANGE']) &&
preg_match('/^bytes=(\d+)-(\d*)/', $_SERVER['HTTP_RANGE'], $arr)){
// Starting byte
$start=$arr[1];
if($arr[2]){
// Ending byte
$end=$arr[2];
}
}
//Check if starting and ending byte is valid
if($start>$end || $start>=$file_size){
header("HTTP/1.1 416 Requested Range Not Satisfiable");
header("Content-Length: 0");
}
else{
// For the first time download
if($start==0 && $end==$file_size){
// Send HTTP OK header
header("HTTP/1.1 200 OK");
}
else{
// For resume download
// Send Partial Content header
header("HTTP/1.1 206 Partial Content");
// Send Content-Range header
header("Content-Range: bytes ".$start."-".$end."/".$file_size);
}
// Bytes left
$left=$end-$start+1;
// Send the other headers
header("Content-Type: application/octet-stream");
header("Accept-Ranges: bytes");
// Content length should be the bytes left
header("Content-Length: ".$left);
header("Content-Disposition: attachment; filename=".$file_db);
// Read file from the given starting bytes
fseek($fh, $start);
// Loop while there are bytes left
while($left>0){
// Bytes to be transferred
// according to the defined speed
$bytes=$speed*1024;
// Read file per size
echo fread($fh, $bytes);
// Flush the content to client
flush();
// Substract bytes left with the tranferred bytes
$left-=$bytes;
// Delay for 1 second
sleep(1);
}
}
fclose($fh);
}
else{
//If the requested file is not exist
//Display error message
echo "File not found!";
}
}
exit();
?>
This code worked for , files are downloading with resume capability...
Please see the RFC on headers on how to report your capabilities to your clients:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
14.5 Accept-Ranges
The Accept-Ranges response-header field allows the server to
indicate its acceptance of range requests for a resource:
Accept-Ranges = "Accept-Ranges" ":" acceptable-ranges
acceptable-ranges = 1#range-unit | "none"
Origin servers that accept byte-range requests MAY send
Accept-Ranges: bytes
but are not required to do so. Clients MAY generate byte-range
requests without having received this header for the resource
involved. Range units are defined in section 3.12.
Servers that do not accept any kind of range request for a
resource MAY send
Accept-Ranges: none
to advise the client not to attempt a range request.
I have the following jquery:
$(".download").click(function(){
$.post('get_bot.php', "url_code="+url_code, function (response) {
alert(response);
});
});
url_code is a variable that has the url for a json structure, here is a live example of the return:
https://services.sapo.pt/Codebits/botmake/01,02,03,04,05,06,07,08,I%20Rule!
Those numbers are parameters to generate different images.
On my get_bot.php page I'm doing:
$urlc=$_POST['url_code'];
$bot = file_get_contents($urlc);
header("content-type: image/png");
echo $bot;
I'm looking into ways on how to get a response as a .png file download, so when the user clicks .download there is a download window prompt with the .png file.
Passing in a correct url and echoing the file_get_content results seems to work fine (although if I try to right click and save the image, it actually saves the php file...)
Any help with this would be great, I'm not very experienced with json structures, so far I've only dealt with array structures, never an image output.
I'm aware I'm probably way off here on getting an actual result, but any pointers would be appreciated.
RFC2616 describes what you need to do. Basically, you need to add
Content-Disposition: attachment; filename="fname.ext"
To the header if I'm not mistaken.
EDIT
Here is a sample script. I've confirmed that this works on two of my servers with different setups.
<?php
header("content-type: image/jpg");
header("Content-Disposition: attachment; filename='pic.jpg'");
readfile('http://lorempixel.com/400/200/');
?>
Just use this function on your get_bot.php to start a download of a file instead of showing it in the browser (should work cross-browser):
function download($file, $path)
{
$size = filesize($path.$file);
#ob_end_clean();
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
header('Content-Type: application/force-download');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header("Content-Transfer-Encoding: binary");
header('Accept-Ranges: bytes');
header("Cache-control: no-cache, pre-check=0, post-check=0");
header("Cache-control: private");
header('Pragma: private');
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
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);
}
$chunksize = 1*(1024*1024);
$bytes_send = 0;
if ($file = fopen($path.$file, 'rb'))
{
if(isset($_SERVER['HTTP_RANGE']))
fseek($file, $range);
while
(!feof($file) &&
(!connection_aborted()) &&
($bytes_send<$new_length) )
{
$buffer = fread($file, $chunksize);
print($buffer);
flush();
$bytes_send += strlen($buffer);
}
fclose($file);
} else die('Error - can not open file.');
die();
}
I am trying to append some details in to a file and add that for download.
I am using JavaScript and PHP for this purpose.. Clicking download button, it will fire an AJAX request.
$.ajax({
url:"php/test.php",
type: 'POST',
data: { totalQuery : test1, },
success: function(finalEntityList){
},
});
Lets assume test.php has a single line code
$html="Test";
Now I want to add this to a file and make it available for download. I've used the code
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=data.csv');
$output = fopen('php://output', 'w');
fwrite($output, $html);
fclose($output);
But the download will not start automatcially... I've to open the POST request link using firebug so that the download will be initiated.. what could be wrong??
Perhaps what you need to do is simply return the path of the file with your AJAX call and then use JavaScript to "initiate" the download by using one of the following -
window.open
window.location.href
$.ajax({
url:"php/test.php",
type: 'POST',
dataType: 'json',
data: { totalQuery : test1, },
success: function(response){
// initiate download using direct path to file
window.location.href = response.URL;
}
});
Now your test.php file will only need to return the URL path for the download file in a JSON format -
$filename = 'data.csv';
$path = $_SERVER['DOCUMENT_ROOT'].'/downloads/';
echo json_encode(array('URL'=>$path.$filename));
You might consider returning the URL as a raw string - but I feel using JSON might be better because you can easily add additional information in to the response without needing additional parsing functions. All this makes it a more robust choice.
It requires some more parameters and headerinfo:
$file = "data.csv";
$mime_type = "text/csv";
$size = filesize($file);
$name = rawurldecode($name);
#ob_end_clean(); //turn off output buffering to decrease cpu usage
// required for IE, otherwise Content-Disposition may be ignored
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
header('Content-Type: ' . $mime_type);
header('Content-Disposition: attachment; filename="'.$name.'"');
header("Content-Transfer-Encoding: binary");
header('Accept-Ranges: bytes');
/* The three lines below basically make the
download non-cacheable */
header("Cache-control: private");
header('Pragma: private');
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
// 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 ($file = fopen($file, 'r'))
{
if(isset($_SERVER['HTTP_RANGE']))
fseek($file, $range);
while(!feof($file) && (!connection_aborted()) && ($bytes_send<$new_length))
{
$buffer = fread($file, $chunksize);
print($buffer); //echo($buffer); // is also possible
flush();
$bytes_send += strlen($buffer);
}
fclose($file);
}
else
die('Error - can not open file.');
I have generated csv file on link click. But I am unable to download file from browser.
Here is my code.
$filename="Payment_Received.csv";
header( 'Content-Description: File Transfer' );
header( 'Content-Disposition: attachment; filename=' . $filename );
header('Content-Type: text/csv; charset=UTF-8');
print_r($output);
// output is string comma separated if i remove die and then execute
// then csv append html data also, so I keep die
ob_flush();
die();
CSV is downloading but for it is with no content.
Please help me out.
If your script outputs this: "1","asd","asds" \n "2","sqda","asds", I believe you will have a hard time generating .csv from that my friend. For CSV output, make sure your data is quoted and escaped properly, I'm sorry to send you to php.net but this comment is the only example I could land that mentions clearly at this issue. There are some code examples on that page for csv output.
Good-luck
Function to force download a file from browser.
function output_file($file, $name, $mime_type='')
{
/*
This function takes a path to a file to output ($file),
the filename that the browser will see ($name) and
the MIME type of the file ($mime_type, optional).
If you want to do something on download abort/finish,
register_shutdown_function('function_name');
*/
if(!is_readable($file)) die('File not found or inaccessible!');
$size = filesize($file);
$name = rawurldecode($name);
/* Figure out the MIME type (if not specified) */
$known_mime_types=array(
"pdf" => "application/pdf",
"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($mime_type==''){
$file_extension = strtolower(substr(strrchr($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(); //turn off output buffering to decrease cpu usage
// required for IE, otherwise Content-Disposition may be ignored
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
header('Content-Type: ' . $mime_type);
header('Content-Disposition: attachment; filename="'.$name.'"');
header("Content-Transfer-Encoding: binary");
header('Accept-Ranges: bytes');
/* The three lines below basically make the
download non-cacheable */
header("Cache-control: private");
header('Pragma: private');
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
// 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 ($file = fopen($file, 'r'))
{
if(isset($_SERVER['HTTP_RANGE']))
fseek($file, $range);
while(!feof($file) &&
(!connection_aborted()) &&
($bytes_send<$new_length)
)
{
$buffer = fread($file, $chunksize);
print($buffer); //echo($buffer); // is also possible
flush();
$bytes_send += strlen($buffer);
}
fclose($file);
} else die('Error - can not open file.');
die();
}
/*********************************************
Example of use
**********************************************/
/*
Make sure script execution doesn't time out.
Set maximum execution time in seconds (0 means no limit).
*/
set_time_limit(0);
$file_path='that_one_file.txt';
output_file($file_path, 'some file.txt', 'text/plain');
Please check code at:
http://w-shadow.com/blog/2007/08/12/how-to-force-file-download-with-php/