Trying to Download large file with php file - php

I am trying to download a large file using the script below. The file downloads, but its named 'download' and the file extension is missing. How can I modify the code below so that the original file name and extension is preserved ? Also is there anyway to automatically detect the mime type and include that as well ?
Thanks a lot in advance.
$path = 'public/Uploads/Films/files/Crank2006.avi';
$size=filesize($path);
$fm=#fopen($path,'rb');
if(!$fm) {
// You can also redirect here
header ("HTTP/1.0 404 Not Found");
die();
}
$begin=0;
$end=$size;
if(isset($_SERVER['HTTP_RANGE'])) {
if(preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches)) {
$begin=intval($matches[0]);
if(!empty($matches[1])) {
$end=intval($matches[1]);
}
}
}
if($begin>0||$end<$size)
header('HTTP/1.0 206 Partial Content');
else
header('HTTP/1.0 200 OK');
header("Content-Type: video/avi");
header('Accept-Ranges: bytes');
header('Content-Length:'.($end-$begin));
header("Content-Disposition: inline;");
header("Content-Range: bytes $begin-$end/$size");
header("Content-Transfer-Encoding: binary\n");
header('Connection: close');
$cur=$begin;
fseek($fm,$begin,0);
while(!feof($fm)&&$cur<$end&&(connection_status()==0))
{ print fread($fm,min(1024*16,$end-$cur));
$cur+=1024*16;
usleep(1000);
}
die();

In Content Disposition header you need to specify file name
$file_url = 'what you want to set'
header("Content-disposition: attachment; filename=\"" . $file_url. "\"");
A good tutorial on forced download php here.
PHP Force Download.
For mime type see the following SO post
Detecting mine-type in PHP.

Just do this below the $path
$path = 'public/Uploads/Films/files/Crank2006.avi';
$filename = array_pop(explode('/',$path)); // Grabbing the filename ... it will be Crank2006.avi
and add the header with filename to your existing headers.
header("Content-disposition: filename=$filename");
EDIT:
Detecting MIME type...
$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo finfo_file($finfo, $filename);

Try Something Like Below
$file='test.pdf' //File to download with Large Size
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('backup/'.$file);
return 1;
} else {
return 0;
}

Related

Why download file from php only 1kb?

I try to force download a pdf file from php that are in server...but all the file that i download only 1kb size.It not the same with actual size do i need to declare file size before download?
<?php
$path = "C:\Users\omamu02\Desktop\TESTPRINT" ;
$file = "NMT PRV PHG 370 2017.pdf";
header("Pragma: public");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-disposition: attachment; filename= $file"); //Tell the filename to the browser
header("Content-type: application/force-download");//Get and show report format
header("Content-Transfer-Encoding: binary");
header("Accept-Ranges: bytes");
readfile($path); //Read and stream the file
get_curret_user();
error_reporting(0);
?>
First of all, you should fix your filename= $file header. Wrap your $file variable with a ' chars at least. Also, you don't need the closing tag in the end of the PHP file.
And I'm not sure about your headers, so I suggest you try the function below, it's quite common for any type of data and already contains some bugfixes and workarounds:
function download_file($file_path, $file_name = null, $file_type = 'application/octet-stream')
{
if ($file_name === null)
{
$file_name = basename($file_path);
}
if (file_exists($file_path))
{
#set_time_limit(0);
header('Content-Description: File Transfer');
header('Content-Type: ' . $file_type);
header('Content-Disposition: attachment; filename="' . str_replace('"', "'", $file_name) . '"');
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_path));
readfile($file_path);
}
exit;
}

How to download image file by force download

I am trying to download image file in CI but getting error when I open download image file. Need help :(
$file_name = $_GET['file_name'];
$file_path = "./ups_printimages/".$file_name;
if(file_exists($file_path))
{
$this->load->helper('download');
$data = file_get_contents($file_path); // Read the file's contents
$name = 'ups_label.png';
force_download($name, $data);
}
else
{
echo "file does not exist";
}
GOD. Found out the solution :)
if(!file)
{
File doesn't exist, output error
die('file not found');
}
else
{
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');
ob_clean();
flush();
readfile($file);
exit;
}
Use header to force download. Use the code below
$file_name = $_GET['file_name'];
$file_path = "./ups_printimages/".$file_name;
if(file_exists($file_path))
{
header('Content-Type: image/jpeg');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"" . basename($file_name) . "\"");
readfile($file_path);
}
else
{
echo "file does not exist";
}
Hope this helps yoiu

Header Content-length not working

I'm doing file download with renaming it before. Everything works except size. I can't set file size with
header('Content-Length: ');
even I'm setting it to
header('Content-Length: 15444544545');
it's not working. I'm using PHP codeigniter framework, where is the problem?
EDIT: more code:
$file_data = array(
'originalName' => $post_info['file_info'][0]['original_name'],
'fakeName' => $post_info['file_info'][0]['file_name'],
'modificationId' => $post_info['file_info'][0]['modification_article_id'],
'extension' => end(explode('.', $post_info['file_info'][0]['original_name'])),
'name' => str_replace(".".end(explode('.', $post_info['file_info'][0]['original_name'])), "", $post_info['file_info'][0]['original_name']),
'filesize' => filesize($post_info['file_info'][0]['file_name'])
);
header('Cache-Control: public');
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename=' . $file_data['name'] . '.' . $file_data['extension']);
header('Content-Length: ' . filesize(base_url().$file_data['fakeName']));
// Read file
readfile(base_url().$file_data['fakeName']);
//print_r($file_data);
echo "<script>window.close();</script>";
EDIT: Solution
there was a server problem
You can try like this:
$mm_type="application/octet-stream";
header("Cache-Control: public, must-revalidate");
header("Pragma: hack");
header("Content-Type: " . $mm_type);
header("Content-Length: " .(string)(filesize($fullpath)) );
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary\n");
readfile($fullpath);
wrong usage of base_url().
where is your file stored?
maybe you can try the constant FCPATH instead of call function base_url()
and you have the filesize stored in $file_data['filesize']
finally there should not be a line echo "<script>window.close();</script>"; in your php script when the file content was output.
You tried with download_helper?? Sintax: force_download($filename, $data).
Also in your code you're reading file through URL. Use file system path instead.
From controller action:
<?php
public function download()
{
//Your code here...
$filePath = realpath(FCPATH.DIRECTORY_SEPARATOR.'uploads/myfile.pdf'); //FakeName????
force_download($file_data['fakeName'], readfile($filePath));
}
If my solution don't works give me a touch to give you other way.
Note: FCPATH is the front controller path, a public folder of server e.g.(/var/www/CodeIgniter). Other path constants are already defined on index.php (front-controller).
A print of $file_data['fakeName'] will be useful.
If your CodeIgniter version don't have download_helper make your own... refer to CI docs for full explanation. There is the force_download function code:
function force_download($filename = '', $data = '')
{
if ($filename == '' OR $data == '')
{
return FALSE;
}
// Try to determine if the filename includes a file extension.
// We need it in order to set the MIME type
if (FALSE === strpos($filename, '.'))
{
return FALSE;
}
// Grab the file extension
$x = explode('.', $filename);
$extension = end($x);
// Load the mime types
if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
{
include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php');
}
elseif (is_file(APPPATH.'config/mimes.php'))
{
include(APPPATH.'config/mimes.php');
}
// Set a default mime if we can't find it
if ( ! isset($mimes[$extension]))
{
$mime = 'application/octet-stream';
}
else
{
$mime = (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension];
}
// Generate the server headers
if (strpos($_SERVER['HTTP_USER_AGENT'], "MSIE") !== FALSE)
{
header('Content-Type: "'.$mime.'"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');
header("Content-Length: ".strlen($data));
}
else
{
header('Content-Type: "'.$mime.'"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary");
header('Expires: 0');
header('Pragma: no-cache');
header("Content-Length: ".strlen($data));
}
exit($data);
}

How to make a file downloadable

Am trying to add file download to my site for audio video and pdf files
Am using the php header() function but instead of downloading the output file, it keeps on downloading the php page instead. here is my code.
header('Content-disposition: attachment;
Content-type: audio/mpeg;
filename=thefile.type');
You need to write the contents of the file out, e.g.
header('Content-disposition: attachment;
Content-type: audio/mpeg;
filename=thefile.type');
echo file_get_contents("thefile.type");
This works pretty well
if (file_exists("audio/thefile.type"))
{
if (FALSE!== ($handler = fopen('thefile.type', 'r')))
{
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment;
filename=audio/thefile.type');
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('thefile.type')); //Remove
//Send the content in chunks
while(false !== ($chunk = fread($handler,4096)))
{
echo $chunk;
}
}
exit;
}
else{
echo "<h1>Content error</h1><p>The file does not exist!</p>";
}

PHP Force Download Causing 0 Byte Files

I'm trying to force download files from my web server using PHP.
I'm not a pro in PHP but I just can't seem to get around the problem of files downloading in 0 bytes in size.
CODE:
$filename = "FILENAME...";
header("Content-type: $type");
header("Content-Disposition: attachment;filename=$filename");
header("Content-Transfer-Encoding: binary");
header('Pragma: no-cache');
header('Expires: 0');
set_time_limit(0);
readfile($file);
Can anybody help?
Thanks.
You're not checking that the file exists. Try using this:
$file = 'monkey.gif';
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;
}else
{
echo "File does not exists";
}
And see what you get.
You should also note that this forces a download as an octet stream, a plain binary file. Some browsers will struggle to understand the exact type of the file. If, for example, you send a GIF with a header of Content-Type: application/octet-stream, then the browser may not treat it like a GIF image. You should add in specific checks to determine what the content type of the file is, and send an appropriate Content-Type header.
I use the following method in phunction and I haven't had any issues with it so far:
function Download($path, $speed = null)
{
if (is_file($path) === true)
{
$file = #fopen($path, 'rb');
$speed = (isset($speed) === true) ? round($speed * 1024) : 524288;
if (is_resource($file) === true)
{
set_time_limit(0);
ignore_user_abort(false);
while (ob_get_level() > 0)
{
ob_end_clean();
}
header('Expires: 0');
header('Pragma: public');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Type: application/octet-stream');
header('Content-Length: ' . sprintf('%u', filesize($path)));
header('Content-Disposition: attachment; filename="' . basename($path) . '"');
header('Content-Transfer-Encoding: binary');
while (feof($file) !== true)
{
echo fread($file, $speed);
while (ob_get_level() > 0)
{
ob_end_flush();
}
flush();
sleep(1);
}
fclose($file);
}
exit();
}
return false;
}
You can try it simply by doing:
Download('/path/to/file.ext');
You need to specify the Content-Length header:
header("Content-Length: " . filesize($filename));
Also, you shouldn't send a Content-Transfer-Encoding header. Both of the HTTP/1.0 and HTTP/1.1 specs state that "HTTP does not use the Content-Transfer-Encoding (CTE) field of RFC 1521".
This problem as same as my website project. This code I've used:
<?php
$file = $_SERVER["DOCUMENT_ROOT"].'/.../.../'.$_GET['file'];
if(!file)
{
// File doesn't exist, output error
die('file not found');
}
else
{
//$file_extension = strtolower(substr(strrchr($file,"."),1));
$file_extension = end(explode(".", $file));
switch( $fileExtension)
{
case "pdf": $ctype="application/pdf"; break;
case "exe": $ctype="application/octet-stream"; break;
case "zip": $ctype="application/zip"; break;
case "doc": $ctype="application/msword"; break;
case "xls": $ctype="application/vnd.ms-excel"; break;
case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
case "gif": $ctype="image/gif"; break;
case "png": $ctype="image/png"; break;
case "jpeg":
case "jpg": $ctype="image/jpg"; break;
default: $ctype="application/force-download";
}
nocache_headers();
// Set headers
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public"); // required for certain browsers
header("Content-Description: File Transfer");
header("Content-Type: $ctype");
header("Content-Disposition: attachment; filename=".$file.";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($file));
readfile($file);
}
?>
I think the problem is on the server setting like PHP setting or cache setting, but I don't have any idea to do this my opinion.
i am doing this to download a PDF ...
$filename = 'Application.pdf';
header("Content-Type: application/pdf");
header("Content-Disposition: attachment; filename=$filename");
echo $pdf;
i think you are missing the last row, where you actually send the file contents of whatever you have in $file.
Pablo
The file opened ok for me when I changed the directory to the file location.
$reportLocation = REPORTSLOCATION;
$curDir = getcwd();
chdir($reportLocation);
if (file_exists($filename)) {
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Length: ' . filesize($filename));
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate');
header('Pragma: public');
ob_clean();
flush();
readfile($filename);
}
chdir($curDir);
The trick is to check with file_exists to confirm the correct path.
The big confusion is that for PHP paths you don't need to start with '/' to say your website start path.
'/folder/file.ext' #bad, needs to know the real full path
in php / is the website main path already, you don't need to mention it. Just:
'folder/file.ext' #relative to the / website
This will work with file_exists, header filename, readfile, etc...
if script work work for small files but for huge files return 0 byte file. you must increate memory_limit via php.ini
also you can add the following line before your code
ini_set('memory_limit','-1');

Categories