Download file with AJAX call - php

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.');

Related

PHP readfile() displays the file contents instead of forcing the browser to download the file [duplicate]

I want to require a file to be downloaded upon the user visiting a web page with PHP. I think it has something to do with file_get_contents, but am not sure how to execute it.
$url = "http://example.com/go.exe";
After downloading a file with header(location) it is not redirecting to another page. It just stops.
Read the docs about built-in PHP function readfile
$file_url = 'http://www.myremoteserver.com/file.exe';
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"" . basename($file_url) . "\"");
readfile($file_url);
Also make sure to add proper content type based on your file application/zip, application/pdf etc. - but only if you do not want to trigger the save-as dialog.
<?php
$file = "http://example.com/go.exe";
header("Content-Description: File Transfer");
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"". basename($file) ."\"");
readfile ($file);
exit();
?>
Or, when the file is not openable with the browser, you can just use the Location header:
<?php header("Location: http://example.com/go.exe"); ?>
header("Content-Type: application/octet-stream");
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"file.exe\"");
echo readfile($url);
is correct
or better one for exe type of files
header("Location: $url");
Display your file first and set its value into url.
index.php
<a href="download.php?download='.$row['file'].'" title="Download File">
download.php
<?php
/*db connectors*/
include('dbconfig.php');
/*function to set your files*/
function output_file($file, $name, $mime_type='')
{
if(!is_readable($file)) die('File not found or inaccessible!');
$size = filesize($file);
$name = rawurldecode($name);
$known_mime_types=array(
"htm" => "text/html",
"exe" => "application/octet-stream",
"zip" => "application/zip",
"doc" => "application/msword",
"jpg" => "image/jpg",
"php" => "text/plain",
"xls" => "application/vnd.ms-excel",
"ppt" => "application/vnd.ms-powerpoint",
"gif" => "image/gif",
"pdf" => "application/pdf",
"txt" => "text/plain",
"html"=> "text/html",
"png" => "image/png",
"jpeg"=> "image/jpg"
);
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');
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($file, 'r'))
{
if(isset($_SERVER['HTTP_RANGE']))
fseek($file, $range);
while(!feof($file) &&
(!connection_aborted()) &&
($bytes_send<$new_length)
)
{
$buffer = fread($file, $chunksize);
echo($buffer);
flush();
$bytes_send += strlen($buffer);
}
fclose($file);
} else
die('Error - can not open file.');
die();
}
set_time_limit(0);
/*set your folder*/
$file_path='uploads/'."your file";
/*output must be folder/yourfile*/
output_file($file_path, ''."your file".'', $row['type']);
/*back to index.php while downloading*/
header('Location:index.php');
?>
In case you have to download a file with a size larger than the allowed memory limit (memory_limit ini setting), which would cause the PHP Fatal error: Allowed memory size of 5242880 bytes exhausted error, you can do this:
// File to download.
$file = '/path/to/file';
// Maximum size of chunks (in bytes).
$maxRead = 1 * 1024 * 1024; // 1MB
// Give a nice name to your download.
$fileName = 'download_file.txt';
// Open a file in read mode.
$fh = fopen($file, 'r');
// These headers will force download on browser,
// and set the custom file name for the download, respectively.
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $fileName . '"');
// Run this until we have read the whole file.
// feof (eof means "end of file") returns `true` when the handler
// has reached the end of file.
while (!feof($fh)) {
// Read and output the next chunk.
echo fread($fh, $maxRead);
// Flush the output buffer to free memory.
ob_flush();
}
// Exit to make sure not to output anything else.
exit;
A modification of the accepted answer above, which also detects the MIME type in runtime:
$finfo = finfo_open(FILEINFO_MIME_TYPE);
header('Content-Type: '.finfo_file($finfo, $path));
$finfo = finfo_open(FILEINFO_MIME_ENCODING);
header('Content-Transfer-Encoding: '.finfo_file($finfo, $path));
header('Content-disposition: attachment; filename="'.basename($path).'"');
readfile($path); // do the double-download-dance (dirty but worky)
The answers above me works. But, I'd like to contribute a method on how to perform it using GET
on your html/php page
$File = 'some/dir/file.jpg';
Download
and download.php contains
$file = $_GET['f'];
header("Expires: 0");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
$ext = pathinfo($file, PATHINFO_EXTENSION);
$basename = pathinfo($file, PATHINFO_BASENAME);
header("Content-type: application/".$ext);
header('Content-length: '.filesize($file));
header("Content-Disposition: attachment; filename=\"$basename\"");
ob_clean();
flush();
readfile($file);
exit;
this should work on any file types. this is not tested using POST, but it could work.
you can use download attribute to force download a file:
<a href="https://test.com/aaa.exe" download>click here to download</a>
You can stream download too which will consume significantly less resource.
example:
$readableStream = fopen('test.zip', 'rb');
$writableStream = fopen('php://output', 'wb');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="test.zip"');
stream_copy_to_stream($readableStream, $writableStream);
ob_flush();
flush();
In the above example, I am downloading a test.zip (which was actually the android studio zip on my local machine).
php://output is a write-only stream (generally used by echo or print).
after that, you just need to set the required headers and call stream_copy_to_stream(source, destination).
stream_copy_to_stream() method acts as a pipe which takes the input from the source stream (read stream) and pipes it to the destination stream (write stream) and it also avoids the issue of allowed memory exhausted so you can actually download files that are bigger than your PHP memory_limit.
The following code is a correct way of implementing a download service in php as explained in the following tutorial
header('Content-Type: application/zip');
header("Content-Disposition: attachment; filename=\"$file_name\"");
set_time_limit(0);
$file = #fopen($filePath, "rb");
while(!feof($file)) {
print(#fread($file, 1024*8));
ob_flush();
flush();
}
try this:
header('Content-type: audio/mp3');
header('Content-disposition: attachment;
filename=“'.$trackname'”');
readfile('folder name /'.$trackname);
exit();
http://php.net/manual/en/function.readfile.php
That's all you need. "Monkey.gif" change to your file name. If you need to download from other server, "monkey.gif" change to "http://www.exsample.com/go.exe"

how to save ajax result as pdf file?

Trying to download a file which is dynamically generated by the the data posted. I have the results coming back. I'm just not sure how I can save the results into a proper file locally once the information (stream) is returned from the server.
Here is the ajax call:
function download_pdf(){
alert("made it" + result_array);
$.ajax({
type: "POST",
url: "report_generation/downlaod_pdf.php",
data: { result_array: result_array },
success: function(results){
alert(results);
},
error:
function(xmlHttpRequest, status, error){
alert(xmlHttpRequest + "| ajax failure: could not download haq report | " + status + " | error:" + error);
var xmlHttpRequestStr = "";
for(var x in xmlHttpRequest)
xmlHttpRequestStr = xmlHttpRequestStr + xmlHttpRequest[x];
alert(xmlHttpRequestStr);
}
});
}
This function is called from a hyperlink like so, and the success method is returning...
<a class="haq_button" href="javascript:download_pdf()"><span>Download Report As PDF</span></a>
UPDATE: Here is a snippet of code from the file generation in download_pdf
// set the headers, prevent caching
header("Pragma: public");
header("Expires: -1");
header("Cache-Control: public, must-revalidate, post-check=0, pre-check=0");
header("Content-Disposition: attachment; filename=\"$file_name\"");
// set appropriate headers for attachment or streamed file
if ($is_attachment) {
header("Content-Disposition: attachment; filename=\"$output_file_name\"");
}
else {
header('Content-Disposition: inline;');
header('Content-Transfer-Encoding: binary');
}
// set the mime type based on extension, add yours if needed.
$ctype_default = "application/octet-stream";
$content_types = array(
"exe" => "application/octet-stream",
"pdf" => "application/pdf",
"zip" => "application/zip",
"mp3" => "audio/mpeg",
"mpg" => "video/mpeg",
"avi" => "video/x-msvideo",
);
$ctype = isset($content_types[$file_ext]) ? $content_types[$file_ext] : $ctype_default;
header("Content-Type: " . $ctype);
//check if http_range is sent by browser (or download manager)
if(isset($_SERVER['HTTP_RANGE']))
{
list($size_unit, $range_orig) = explode('=', $_SERVER['HTTP_RANGE'], 2);
if ($size_unit == 'bytes')
{
//multiple ranges could be specified at the same time, but for simplicity only serve the first range
//http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt
list($range, $extra_ranges) = explode(',', $range_orig, 2);
}
else
{
$range = '';
header('HTTP/1.1 416 Requested Range Not Satisfiable');
exit;
}
}
else
{
$range = '';
}
//figure out download piece from range (if set)
list($seek_start, $seek_end) = explode('-', $range, 2);
//set start and end based on range (if set), else set defaults
//also check for invalid ranges.
$seek_end = (empty($seek_end)) ? ($file_size - 1) : min(abs(intval($seek_end)),($file_size - 1));
$seek_start = (empty($seek_start) || $seek_end < abs(intval($seek_start))) ? 0 : max(abs(intval($seek_start)),0);
//Only send partial content header if downloading a piece of the file (IE workaround)
if ($seek_start > 0 || $seek_end < ($file_size - 1))
{
header('HTTP/1.1 206 Partial Content');
header('Content-Range: bytes '.$seek_start.'-'.$seek_end.'/'.$file_size);
header('Content-Length: '.($seek_end - $seek_start + 1));
}
else
header("Content-Length: $file_size");
header('Accept-Ranges: bytes');
set_time_limit(0);
fseek($file, $seek_start);
while(!feof($file))
{
print(#fread($file, 1024*8));
ob_flush();
flush();
if (connection_status()!=0)
{
#fclose($file);
exit;
}
}
// file save was a success
#fclose($file);
exit;
It's not posible. Only you can do is to open new browser window with that PDF url or change location of current window like that: window.location = 'report_generation/downlaod_pdf.php';
This is not possible using javascript/ajax. You have to use regural download link, or in your case form. If you want to have some error handling using javascript if pdf generation fails and still keep the same page open, you can submit into a hidden iframe.
You can create a dynamic form and submit it, it will open a new window/tab and if it fails you can show a message in that page. In anyway, the right way to handle and track an exception is not on the receiver, but sender (download_pdf.php)
To create a dynamic form:
var VerifyForm = document.createElement("form");
VerifyForm.target = "_blank"; //You must specify here your target
VerifyForm.method = "POST";
VerifyForm.action = "download_pdf.php";
var dataInput = document.createElement("input");
dataInput.type = "hidden";
dataInput.name = "mydata"; //var name
dataInput.value = value; //var value
VerifyForm.appendChild(dataInput); //Apend var to form, repeat for n
document.body.appendChild(VerifyForm);
VerifyForm.submit();
If you still try to it at your own way, is impossible, I recommend you read more about what means the capital "A" in "Ajax"
You can try to force the download of the file by adding these HTTP headers in the downlaod_pdf.php
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: public");
header("Content-Type: application/pdf");
header("Content-Disposition: attachment; filename=$your_file_name");
header("Content-Transfer-Encoding: binary");
readfile($your_file_content);
EDIT : and also add window.location.href = your_php_script_path in the js file

Download of large files does not work

Hey i have following code to download a large file but the download does stop everytime without finish the download
function download($file)
{
include('logger.php5');
$log = new Logging();
$log->lfile('download.log');
ini_set('max_execution_time', 86400);
//header('Location: '.$file);
$filesize = filesize($file);
$filename = pathinfo($file, PATHINFO_BASENAME);
$filext = pathinfo($file, PATHINFO_EXTENSION);
$mime = include('mime.php5');
$log->lwrite(ini_get('max_execution_time'));
$log->lwrite(sprintf('%s %s %s %s', $filename, $filext, $mime[$filext], human_filesize($filesize)));
$log->lclose();
#ob_end_clean();
session_write_close();
header("Content-Description: File Transfer");
header("Content-Type: ".$mime[$filext]);
header("Content-Disposition: ".
(!strpos($HTTP_USER_AGENT,"MSIE 5.5")?"attachment; ":"").
"filename=".$filename);
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".$filesize);
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header('Pragma: public');
header('Expires: 0');
$done = readfile_chunked($file);
}
function readfile_chunked($filename,$retbytes=true) {
$chunksize = 1*(1024*1024); // how many bytes per chunk
$buffer = '';
$cnt =0;
// $handle = fopen($filename, 'rb');
$handle = fopen($filename, 'rb');
if ($handle === false) {
return false;
}
while (!feof($handle)) {
$buffer = fread($handle, $chunksize);
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;
}
Each time i call the script the download start up but stops after 400MB, the file itself is 778MB big.
Someone can see a problem with the code?
UPDATE
after try to log the return value of readfile_chunkedit feels like the script gets stoped not the download itself. Because i cant get a log entry after the readfile_chunked call.
It could be a problem with the filesize function in PHP. There are known bugs for big file size reading and as you're sending it with the file as an header I would suggest you to try the script without using this line:
header("Content-Length: ".$filesize);
Oh and maybe you can take a look at this line:
header("Content-Transfer-Encoding: binary");
I think the encoding should be checked for each file. Like this:
$finfo = finfo_open(FILEINFO_MIME);
//check to see if the mime-type starts with 'text'
return substr(finfo_file($finfo, $filename), 0, 4) == 'text';
If it's a textfile you should use ASCII ofcourse. Has nothing to do with the question but I think it's an useful addition to your script :)

Download file_get_contents response

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();
}

Webkit and Excel file(PHPexcel)

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();
}

Categories