I am trying to download an image from website using php with the following code.
Currently it idendtify and downloads the file. but the
file downloaded is not opening and it shows as corrupted. what is the issue in the below code ?
Also I am embedding this page in one of my mobile app. will it work in mobile android devices too
<?php
$file = "http://example.com/animals/1.jpg";
// Parse Info / Get Extension
$fsize = filesize($file);
$path_parts = pathinfo($file);
$ext = strtolower($path_parts["extension"]);
// Determine Content Type
switch ($ext)
{
case "gif": $ctype="image/gif"; break;
case "png": $ctype="image/png"; break;
case "jpeg":
case "jpg": $ctype="image/jpg"; break;
default: die('Wrong Extension');
}
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false); // required for certain browsers
header("Content-Type: $ctype");
header("Content-Disposition: attachment; filename=\"Test".basename($file)."\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . $fsize);
ob_clean();
flush();
readfile($file);
exit();
?>
You need to send data stream to browser.
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream'); // change this will work for you.
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
Related
I have this code to force a download, $file is a url of a existing .jpg, .png or .pdf file (I made sure it exists)
<?php
$file = $_REQUEST['file'];
$file_extension = end(explode('.', $file));
$file_name = end(explode('/', $file));
switch ($file_extension) {
case 'jpg':
header('Content-Type: image/jpeg');
header('Content-Disposition: attachment; filename='.$file_name);
header('Pragma: no-cache');
readfile($file);
break;
case 'png':
header('Content-Type: image/png');
header('Content-Disposition: attachment; filename='.$file_name);
header('Pragma: no-cache');
readfile($file);
break;
case 'pdf':
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename='.$file_name);
header('Pragma: no-cache');
readfile($file);
break;
}
But it's downloading an empty (0KB) file (with the correct name)
Any thought about what may be happening?
Since file_get_contents() return null too, your problem is probably a setting in the php.ini configuration.
The parameter allow_url_fopen must be On.
That's because you are missing a Content-Length header.
Try this:
$file = $_REQUEST['file'];
$file_extension = end(explode('.', $file));
$file_name = end(explode('/', $file));
switch ($file_extension) {
case 'jpg':
header('Content-Type: image/jpeg');
break;
case 'png':
header('Content-Type: image/png');
header('Content-Disposition: attachment; filename='.$file_name);
break;
case 'pdf':
header('Content-Type: application/pdf');
break;
}
header('Content-Disposition: attachment; filename='.$file_name);
header('Pragma: no-cache');
header('Content-Length: ' . filesize($file));
// You may want to add this headers too (If you don't want the download to be resumable - I think).
header('Expires: 0');
header('Cache-Control: must-revalidate');
// And you may consider flushing the system's output buffer if implicit_flush is turned on in php.ini.
flush();
// If you have the file locally.
readfile($file);
// Otherwise,
echo file_get_contents($file); // You should have allow_url_include on in php.ini
Didn't get to try it, but it should work.
I want to implement a button that downloads an image uploaded in a external server.
HTML 5 download attribute does work, but in FireFox and IE10 it opens the image in a new window and the user still have to use the right click to save image as.
Save
I can force the download using PHP if the image is located in my server.
<?php
$file = $_GET['file'];
download_file($file);
function download_file( $fullPath ){
// Must be fresh start
if( headers_sent() )
die('Headers Sent');
// Required for some browsers
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
// File Exists?
if( file_exists($fullPath) ){
// Parse Info / Get Extension
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
// Determine Content Type
switch ($ext) {
case "png": $ctype="image/png"; break;
case "jpeg":
case "jpg": $ctype="image/jpg"; break;
default: $ctype="application/force-download";
}
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: $ctype");
header("Content-Disposition: attachment; filename=\"".basename($fullPath)."\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".$fsize);
ob_clean();
flush();
readfile( $fullPath );
} else
die('File Not Found');
}
?>
HTML
Download1
Is there a way to avoid with the HTML5 download attribute the problem to open the image in a new window in FF and IE? -Chrome works great-.
Is there a way to do it with PHP but when the image is located at and external server?
It will be great to do it any way, HTML 5 or PHP. Thanks for any help. Greetings.
Copy it to your server and download from there.
file_put_contents($fullpath,
file_get_contents('https://externalserver/images/image.png'));
header("Pragma: public"); // wtf?
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
// omg what have you been reading?
header("Cache-Control: private",false);
// obviously not rfc 2616
header("Content-Type: $ctype");
header("Content-Disposition: attachment; filename=\"".basename($generatedPath)."\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".$fsize);
ob_clean();
flush();
readfile( $fullPath );
For the php part. If you have the URL of the image you can use many approach.
An easy one would be a simple call to file_get_content to retrieve the image binary data in a variable .
After you can save it to the disk or do whatever you want with it.
I'm php programmer of beginner. I have write code to download file of any type.
When I click on download link it goes to download.php file. I work on local server but not working on server.
My code is:
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream'); //application/force-download
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();
Is my code wrong or does server need some settings?
this is code tested online its working fine. u can try this
$folder_name = $_GET['fol_name'];
$file_directory = "../img/files/$folder_name"; //Name of the directory where all the sub directories and files exists
$file = $_GET['file_name']; //Get the file from URL variable
$file_array = explode('/', $file); //Try to seperate the folders and filename from the path
$file_array_count = count($file_array); //Count the result
$filename = $file_array[$file_array_count-1]; //Trace the filename
$file_path = dirname(__FILE__).'/'.$file_directory.'/'.$file; //Set the file path w.r.t the download.php... It may be different for u
if(file_exists($file_path)) {
header("Content-disposition: attachment; filename={$filename}"); //Tell the filename to the browser
header('Content-type: application/octet-stream'); //Stream as a binary file! So it would force browser to download
readfile($file_path); //Read and stream the file
}
else {
echo "Sorry, the file does not exist!";
}
thank u !!
by using code written by me. this problem is solved.
if anybody have same issue. please try this code. it works for me very good.
$file_name ='../img/files'.DS.$_GET['file'];
if(is_file($file_name)) {
if(ini_get('zlib.output_compression')) {
ini_set('zlib.output_compression', 'ON');
}
switch(strtolower(substr(strrchr($file_name, '.'), 1))) {
case 'pdf': $mime = 'application/pdf'; break; // pdf files
case 'zip': $mime = 'application/zip'; break; // zip files
case 'jpeg': $mime = 'image/jpeg'; break;// images jpeg
case 'jpg': $mime = 'image/jpg'; break;
case 'mp3': $mime = 'audio/mpeg'; break; // audio mp3 formats
case 'doc': $mime = 'application/msword'; break; // ms word
case 'avi': $mime = 'video/x-msvideo'; break; // video avi format
case 'txt': $mime = 'text/plain'; break; // text files
case 'xls': $mime = 'application/vnd.ms-excel'; break; // ms excel
default: $mime = 'application/force-download';
}
header('Content-Type:application/force-download');
header('Pragma: public'); // required
header('Expires: 0'); // no cache
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Last-Modified: '.gmdate ('D, d M Y H:i:s', filemtime ($file_name)).' GMT');
header('Cache-Control: private',false);
header('Content-Type: '.$mime);
header('Content-Disposition: attachment; filename="'.basename($file_name).'"');
header('Content-Transfer-Encoding: binary');
//header('Content-Length: '.filesize($file_name)); // provide file size
header('Connection: close');
readfile($file_name);
exit();
}
thank u!!!
I recently got this problem and discovered that this was being caused by ob_clean();
and flush(); These are causing the program to download garbage.
I tried various combinations to flush the buffer and the only one which worked on the hosting server was
ob_end_clean();
print $object->body;
It might work with echo as well but i didn't try it
use this
public function loadfile($fl)
{
$mime = 'application/force-download';
header('Pragma: public'); // required
header('Expires: 0'); // no cache
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: private',false);
header('Content-Type: '.$mime);
header('Content-Disposition: attachment; filename="'.basename($fl).'"');
header('Content-Transfer-Encoding: binary');
header('Connection: close');
readfile($fl); // push it out
exit();
}
Generally, browsers show the image and pdf files without embedding them in html. I need some codes to make these files not to show in the browsers but make them downloadable like doc files.
Please help me out with this.
This isn't up to you, it is up to the browser.
However, you can make a suggestion as to what to do with it by setting the content-disposition header...
header("Content-Disposition: attachment; filename=\"yourfilename.pdf\"");
Read the doc on the header() function: http://php.net/manual/en/function.header.php
In case this isn't clear... this is for whatever resource is returned by the PHP document. You may need a readfile() in there to do what you are trying to do.
Set a couple of headers:
$filename = ...;
$mime_type = ...; //whichever applicable MIME type
header('Pragma: public');
header('Expires: 0');
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Type: $mime_type");
header('Content-Length: ' . filesize($filename));
readfile($filename);
<?php
header('Content-disposition: attachment; filename=myfile.pdf');
header('Content-type: application/pdf');
readfile('myfile.pdf');
?>
You want to send a content type header to make the browser download the file.
If you aren't' generating it dynamically, you will need to read it off the disk first.
$fullPath = "/path/to/file/on/server.pdf";
$fsize = filesize($fullPath);
$content = file_get_contents($fullPath);
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false); // required for certain browsers
header("Content-Type: application/pdf");
header("Content-Disposition: attachment; filename=\"".basename($fullPath)."\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".$fsize);
echo $content;
try this one :
$file = 'youfile.fileextention';
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;
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');