php force download on mobile browsers - php

I'm trying to force download a image file (jpg for example) using php. So I have a script here force.php and here would be the code:
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-Description: File Transfer');
header("Content-Type: image/jpeg");
header('Content-Length: ' . filesize($file));
header('Content-Disposition: attachment; filename=test.jpg');
readfile($file);
Now the problem is for some browsers (mobile phone browsers especially), it'll work properly and prompt test.jpg for the user to save. However on some browser, it'll prompt force.php as download. Any solution?
Thank you!

Content disposition header highly depends on how a particular browser implements it. Sometimes there are encoding issues (I do not see in your case).
The document at Test Cases for HTTP Content-Disposition shows behavior for various browsers.

To be safe with mobile browsers you should consider having the http request's last part be equal to the actual filename of the attachment, for example http://some.url/download/test.jpg .
Use apache mod_rewrite or similar to route such requests to your download script.

Related

PHP - Force download or view in browser depending on file type

I am using the following headers to force a download but I need to try and have the browser display certain files like PDF's and JPG's if that is the file type, finding the exntension is easy enough but how can I alter these headers to open the file in the browser?
header("Content-Description: File Transfer");
header("Content-type: application/octet-stream");
$header="Content-Disposition: attachment; filename=".$filename.";";
header($header);
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");
In order to display a file in the browser, you'll need to use the correct MIME type. You can set it yourself based on file extension, or you can use the finfo module:
function getContentType($filename) {
$finfo = new finfo(FILEINFO_MIME);
return $finfo->file($filename);
}
header("Content-Type: " . getContentType($filename));
Without this, the browser will probably assume that it can't handle the application/octet-stream content, and force a download anyway.
You should also only send the Content-Disposition header if you want to force the file to be downloaded. If you remove that header, then the browser can decide if it should display the file or download it.

Serving Up PDF File Download Fails in IE7/8

I am using Zend and have some files outside of the webroot that I would like to be able to serve up. I have tried two approaches, both of which work in all browsers except for versions of IE 8 or lower.
The two (working) approaches that I have tried are the following:
// Approach #1
header('Content-Type: application/pdf');
header("Pragma: ");
header("Content-Disposition: attachment; filename=\"$filename\"");
//header('Content-Transfer-Encoding: binary');
header("Pragma: no-cache");
header("Expires: 0");
readfile($file);
// Approach #2
$this->getResponse()
->setHeader('Content-Disposition', "attachment; filename=$filename")
->setHeader('Content-type', 'application/x-pdf');
fpassthru($file);
Like I said, both approaches work in modern browsers (even IE9) but not in older versions of IE. The error I am getting is the following: http://cl.ly/image/1G3x370b1s09
I have looked into several posts on this topic and tried more different combinations of headers than I can even count. Is there a more bulletproof way of handling this functionality that wont cause issues with older browsers?
Thanks!
I've fought with this before and I think it stems from caching headers.
There's three: Expires, Cache-Control (HTTP 1.1), and Pragma (HTTP 1.0). My experience has been the older versions of IE like to see all three of these headers. Try using the following prior to any other headers and content you send:
header("Cache-control: no-cache");
header("Pragma: no-cache");
header("Expires: -1");
This article from Microsoft goes in to more discussion about the caching headers.
This is what I have done in the past to get it to work:
$file = $fileInfo->openFile('r');
header("Pragma: public");
header("Cache-Control: public");
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="'.$file->getFilename().'"');
print $file->fpassthru()
Against my will I gave up on trying to fight with headers and completely changed the way I am handling file downloads. When a user requests a file now, it is temporarily hashed, copied to an area that the web-server can see, the user is redirect to that file and once they leave the download area the file is deleted. If they go inactive the file is deleted automatically at a set interval.
Thank you for all of the input kulishch and how ironic is it that you are from Minnesota as well!? Happy Holidays!
-- Nicholas
Follwing the advice at http://support.microsoft.com/default.aspx?scid=KB;EN-US;q316431&, these headers worked for me:
header("Cache-control: max-age=3600, must-revalidate");
header("Pragma: public");
header("Expires: -1");
I always get caught out by this! :(

Linking to a forced download script in a pdf

I am generating dynamic PDF reports in PHP and having some issues with links to the web.
My links are to a PHP script that forces the download of a file attachment. This script works perfectly in all browser when accessed via the browser. It also works from the PDF in all browser except Internet Explorer.
Instead of IE seeing the file as a PDF, PNG, or whatever the file is, the download prompt says the document type is: "HTML Plugin Document"
If the user clicks "Open" or "Save" IE says it cannot download the file and gives the filename as "index2.php". That is the beginning of the URI of address.
The correct filesize is given so I know it is getting the file. Maybe it is a header issue?
Here is the header I'm creating on the download script:
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT;");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT;");
header("Pragma: no-cache;"); // HTTP/1.0
header('Content-Type: '.$file->file_mime_type.';');
header("Content-Description: File Transfer");
header("Cache-Control: public");
header('Content-Disposition: attachment; filename="'.$file->file_name.'";');
header('Content-Length: '.$file->file_size.';');
header('Content-transfer-encoding: binary');
Any input would be greatly appreciated.
Here's what I use and that is proven to work:
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="'.$file->file_name.'"');
readfile($filename);
have you tried something like this?
header('Content-Disposition: attachment; filename="'.$file->filename.'"');
It might be worth mentioning that there is also a known issue on several versions of IE when transferring files over SSL which requires the following work around:
header("Cache-Control: maxage=1");
header("Pragma: public");
There is more information regarding this bug here: http://support.microsoft.com/kb/812935

Problems with header() when displaying a PDF file in IE8

So, I have a file that sends the following:
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: private");
header("Content-type: application/pdf");
header("Content-disposition: inline; filename=file.pdf");
header("Content-length: 7735");
then I echo out the file - it is a PDF file.
Works fine in IE6 & 7 on XP (and FF for that matter)
The very same code shows nothing when running on IE8 on either XP or Vista.
There are no security warnings, etc so I don't think it has to do with that.
And, if my memory serves me correctly, this worked on IE8 a while ago.
What am I doing wrong here? Am I missing something out of the headers?
Is there a way for me to see what header information normal comes over when viewing a PDF in IE8 so I know what to emulate?
After looking at things it still works in IE8 EXCEPT when SSL is on
Under HTTPS and IE8, those headers fix the download problem:
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Pragma: public");
Other X-something headers did not make any difference.
It has probably to do do with the SSL. I read this article (in German, with code examples) where the author set the following header:
header('Pragma: anytextexeptno-cache', true);
I'm not sure what is needed, but here is what you could do.
Put the file temporarily in a public place on your server, make syre you can download that with a direct link in IE8, Use firefox LiveHTTP headers or similar to grab all headers that the server sends. Spit them out in exactly the same way and order in your script. (And don't forget to delete the file).
Something I want to add, as I faced this problem, too, in a slightly different way using Joomla.
Normal PDF-Output of content worked fine, in all browsers.
But the generation of a pdf from within my own component (using JDocument, tho) generated the bevahiour mentioned above.
My solution: Explicitly enable caching for my component using the following statement in view.html.php:
JResponse::allowCache(true);
Maybe that helps somebody.
I'm using HTTPS and i had some problems, but using those headers the download did.
Try it.
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Pragma: public");
header("X-Download-Options: noopen "); // For IE8
header("X-Content-Type-Options: nosniff"); // For IE8
header("Content-type: application/pdf");
header("Content-disposition: inline; filename=file.pdf");
header("Content-length: 7735");
The problem is you cant direct open. Just save.
Possibly related: Can't display PDF from HTTPS in IE 8 (on 64-bit Vista)

How can I allow a download to pause/resume?

Normally, when I want to allow a user to download a file without revealing the exact location, I just use something like this to let them download the file:
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"" . $filename) . "\";");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($filename));
readfile("$filename");
But if they are using a modern browser or other download client, and they pause the download and try to resume it, the script (assuming they are still authenticated or whatever) will resend the headers and the file contents from the beginning, thus breaking the download, and basically requiring the file to be redownloaded from the beginning.
How can I enable my script to compensate for paused (and consequentially, resumed) downloads?
Use php's built-in fopen to open the file and then fseek to the right place (based on the range in the request header) and then return the partial file using fpassthru instead of using readfile.
You can find some example code in php under the comments for fread
You need to read the request headers like Range, If-Range, etc then seek to the correct location in the file. Normally a web-server would do this for you on an ordinary file. It's a bit complex but here's something that might get you started:
http://forums.asp.net/t/1218116.aspx
http://www.notes411.com/dominosource/tips.nsf/0/480C4E3BE825F69D802571BC007D5AC9!opendocument
For the second link the code is in part 12

Categories