I have a question, how can I do something like this:
header("Content-Disposition: inline; filename=result.pdf");
header("Content-type: application/x-pdf");
With Zend Framework, I have tried:
$this->getResponse()
->setHeader('Content-Disposition:inline', ' filename=result.pdf')
->setHeader('Content-type', 'application/x-pdf');
But doesn't work correctly.
Your statement to set the response headers is slightly malformed:
$this->getResponse()
->setHeader('Content-Disposition', 'inline; filename=result.pdf')
->setHeader('Content-type', 'application/x-pdf');
The above should work - please note the difference in the Content-Disposition-header.
By the way... When you want to force a download box (instead of loading the document in the browser) you should use the Content-Disposition attachment.
$this->getResponse()
->setHeader('Content-Disposition', 'attachment; filename=result.pdf')
->setHeader('Content-type', 'application/x-pdf');
Depending on the browser it may be possible that you also have to set the Content-Length or change the Content-type to a combination (multiple headers) of one or more of application/force-download, application/octet-stream and/or application/download. And as I wrote in the comment sometimes caching headers may interfere with your download. Check to see which caching-headers are sent.
Late to the table, I can recommend this action helper as a simple, reusable component for sending files or in memory data to the browser.
Has options for caching, disposition and can utilise Apache Sendfile
My guess is that you're doing something like:
$this->getResponse()
->setHeader('Content-Disposition:inline', ' filename=result.pdf')
->setHeader('Content-type', 'application/x-pdf');
fpassthru($filename);
exit();
or something.
The response here will never be rendered (which renders the headers). The response is rendered during post-action printing, usually.
You will have to directly set the headers (as you noted in the non-oo code), or use $this->getResponse()->sendHeaders() directly.
I had a header set.
It was not set, but ADDED.
So I had a Content-Type of text/html and also application/pdf.
Flagging the Content-Type with TRUE made the download possible in IOS and other devices which showed only cryptic symbols after the download or an error:
->setHeader('Content-type', 'application/x-pdf', true);
setHeader($name, $value, $replace = false)
from:
https://framework.zend.com/manual/1.12/de/zend.controller.response.html
Solved
$this->getResponse()
->setHeader('Content-Disposition:inline', ';filename=result.pdf')
->setHeader('Content-Type', 'application/x-pdf');
Related
I use Symfony2 Framework and use the following code to export an xml file:
$response->setStatusCode(200);
$response->headers->set('Content-Type', 'application/xml');
$response->headers->set('Content-Description', 'Submissions Export');
$response->headers->set('Content-Disposition', 'attachment; filename="' . $filename .'"');
$response->headers->set('Content-Transfer-Encoding', 'binary');
$response->headers->set('Pragma', 'no-cache');
$response->headers->set('Expires', '0');
I does not matter whether I take "Content-Transfer-Encoding" or "Pragma" or all of them except "Content-Type" and "Content-Disposition" away. The result in Chrome is always: "filename-, attachment" (without the ").
In Firefox this works fine.
So for instance, if I have a file called home.xml Firefox will download home.xml, whereas Chrome will give me home.xml-, attachment.
I know this is a pretty old discussion, but if anyone gets here looking for help with this, I determined that chrome seems to want a semicolon at the end of the filename and then it's happy. As in (VBScript):
Response.AddHeader "Content-Disposition", "attachment;filename=Something.xls;"
That fixed it for me.
-Dave
I had the same problem in ZEND because I found a lot of non working stuff I wanted to add my anwser to this post. Since it took me a while to solve it thought more users and developers would wanted to know how I solved it. I add this just before my fopen call.
header('Content-Disposition: attachment; filename='.time().'.csv');
Solved the issue for me. Before I used a contextswitched what was buggy but now it works as a charm. Do not forget to remove previous content disposition headers hence you might get a double header error.
My searching leads me to believe this is an issue with the headers being set for the response. This application is built using the Zend framework, and here are the headers being set (this response contains information about a file upload):
$response
->setHeader('Expires', 'Mon, 26 Jul 1997 05:00:00 GMT')
->setHeader('Cache-Control', 'private, no-cache')
->setHeader('Pragma', 'no-cache')
->setHeader('Content-Disposition', 'inline; filename="files.json"')
->setHeader('X-Content-Type-Options', 'nosniff')
->setHeader('Content-type', 'application/json; charset=UTF-8');
This is the contents of the "files.json":
{"webpath":"http://www.domain.com/avatar/38b/3ef/f8b/a4c62a71.jpg","file_id":"484","height":250,"width":250}
Edit: I'm having this issue in all versions of IE, including IE9. I have also attempted to use 'text/plain' for the Content-type, with no avail. Also fixed the typo on the word "private".
When I am returning json I set the following in whateverAction():-
$this->getResponse()->setHttpResponseCode(200);
$this->getResponse()->setHeader('Content-Type', 'application/json');
$this->getResponse()->setBody($Json());
That's it, nothing else and it works across all browsers. All those I can test anyway, which includes IE 9.
If browsers ask you to download a JSON document nothing goes wrong. By default browsers do not display JSON which has a proper content type inline unless you have some extension installed (e.g. JSONView in Firefox).
If you just want to view the JSON created by your script, use such an extension or temporarily use a text content type (such as text/plain or text/javascript). In other cases leave it as-is since JSON should be sent with a proper content type.
Have you tried setting Content-Disposition to just "inline" (i.e. remove '; filename="files.json"')?
The headers tell IE to download the file. I would remove
->setHeader('Content-Disposition', 'inline; filename="files.json"')
because I think this one triggers the download.
If that's not the case, I would remove all headers at first, then review if they are all written properly (see "private") and test first with no headers and then adding them one by one to find out which one triggers your problem. Then please write which one it is to look further into it.
I am having issue with setting headers for xls file while downloading through Zend Framework.
I have tried this but not working...
$this->getResponse()
->setHeader('Content-type', 'application/vnd.ms-excel')
->setHeader('Content-Disposition', 'attachment; filename=test.xls');
Still it shows some binary data. and not setting headers.
Please help me though this.
Try
->setHeader('Content-type', 'application/vnd.ms-excel', true)
Use true in the third argument to force replacement of the header
and add
->setHeader('Content-Length', ...)
I have written the following PHP function but still get the prompt to download the file:
function navigateToBytes($contentType, $bytes){
header('Content-Type: ' .$contentType);
//header('Content-Transfer-Encoding: binary'); // UPDATE: as pointed out this is not needed, though it does not solve the problem
header('Content-Length: '.strlen($bytes));
ob_clean();
flush();
echo $bytes;
}
An example of calling the function:
navigateToBytes('image/jpeg', $bytes); // UPDATE: turns out this does work, using image/tiff for tiff images is when the browser does not display the image
where $bytes are the bytes as read from the file.
Apologies all - turns out I was having the problem because the images I was testing were TIFF's (with the Content-Type correctly set to image/tiff) when I used a JPEG the browser would display the image!
Ultimately it is up to the browser to decide whether it can display the Content-Type you are sending.
For the record the only headers I needed to change was
Content-Type,
I should set
Content-Length
too unless I set
Transfer-Encoding: chunked
Try the HTTP header "Content-Disposition: Inline", however some browsers may try to save the user from seeing binary data. Here is a random blog article on that HTTP header:
http://dotanything.wordpress.com/2008/05/30/content-disposition-attachment-vs-inline/
That seems like correct behavior to me. The browser is a viewport for humans to view things in. Humans, by and large, don't want to view binary data. What do you think should happen?
Random Advice: If there's a site that's doing what you want to do, use curl to sniff the headers they're sending.
curl -I http://example.com/path/to/binary/file/that/displays/in/browser
and then use the exact same headers in your own script.
As a start, get rid of things that do not exist in HTTP (Content-Transfer-Encoding).
Then get an HTTP tracing tool, such as the Live HTTP headers plugin for Firefox, and compare "your" headers with those received for a working image.
In doubt, post the HTTP trace here.
I've come across a rather interesing (and frustrating) problem with IE6. We are serving up some server generated pdfs and then simply setting headers in PHP to force a browser download of the file. Works fine and all, except in IE6 but only if the windows user account is set to standard user (ie. not administrator).
Since this is for a corporate environment, of course all their accounts are setup this way. Weird thing is, that in the download dialog, the Content-Type is not recognized:
header( 'Pragma: public' );
header( 'Expires: 0' );
header( 'Cache-Control: must-revalidate, pre-check=0, post-check=0' );
header( 'Cache-Control: public' );
header( 'Content-Description: File Transfer' );
header( 'Content-Type: application/pdf' );
header( 'Content-Disposition: attachment; filename="xxx.pdf"' );
header( 'Content-Transfer-Encoding: binary' );
echo $content;
exit;
I also tried writing the file content to a temporary file first so I could also set the Content-Length in the header but that didn't help.
These headers are bogus!
Content-Transfer-Encoding: binary
This header is copied from e-mail headers. It doesn't apply to HTTP simply because HTTP doesn't have any other mode of transfer than binary. Setting it makes as much sense as setting X-Bits-Per-Byte: 8.
Cache-control: pre-check=0, post-check=0
These non-standard values define when IE should check whether cached content is still fresh. 0 is the default, so setting it to 0 is waste of time. These directives apply only to cacheable content, and Expires:0 and must-revalidate hint that you wanted to make it non-cacheable.
Content-Description: File Transfer
This is another e-mail copycat. By design this header doesn't affect download in any way. It's just informative free-form text. It's technically as useful as X-Hi-Mom: I'm sending you a file! header.
header( 'Cache-Control: must-revalidate, pre-check=0, post-check=0' );
header( 'Cache-Control: public' );
In PHP second line completely overwrites the first one. You seem to be stabbing in the dark.
What really makes a difference
Content-Disposition: attachment
You don't have to insert filename there (you can use mod_rewrite or index.php/fakefilename.doc trick – it gives much better support for special characters and works in browsers that ignore the optional Content-Disposition header).
In IE it makes difference whether file is in cache or not ("Open" doens't work for non-cacheable files), and whether user has plug-in that claims to support type of file that IE detects.
To disable cache you only need Cache-control:no-cache (without 20 extra fake headers), and to make file cacheable you don't have to send anything.
NB: PHP has horrible misfeature called session.cache_limiter which hopelessly screws up HTTP headers unlesss you set it to none.
ini_set('session.cache_limiter','none'); // tell PHP to stop screwing up HTTP
some versions of IE seem to take
header( 'Expires: 0' );
header( 'Cache-Control: must-revalidate, pre-check=0, post-check=0' );
way too seriously and remove the downloaded content before it's passed to the plugin to display it.
Remove these two and you should be fine.
And make sure you are not using any server-side GZIP compression when working with PDFs because some versions of Acrobat seem to struggle with this.
I know I'm vague here, but above tips are based on real-world experience I got using a web application serving dynamically built PDFs containing barcodes. I don't know what versions are affected, I only know that using the two "tricks" above made the support calls go away :p
I have had the exact same problem about a year ago, and after much googling and research, my headers (from Java code) look for IE6 & PDFs like this:
response.setHeader("Content-Type", "application/pdf "; name=" + file.getName());
response.setContentType("application/pdf");
response.setHeader("Last-Modified", getHeaderDate(file.getFile());
response.setHeader("Content-Length", file.getLength());
Drop everything else.
There is apparently something a bit whacky with IE6, caching, forced downloading and plug-ins. I hope this works for you...a small difference for me is that the request initially comes from a Flash swf file. But that should not matter.
I appreciate the time you guys spent on this post. I tried several combinations and finally got my symfony project to work. Here I post the solutions in case anyone will have the same problem:
public function download(sfResponse $response) {
$response->clearHttpHeaders();
$response->setHttpHeader('Pragma: public', true);
$response->addCacheControlHttpHeader("Cache-control","private");
$response->setContentType('application/octet-stream', true);
$response->setHttpHeader('Content-Length', filesize(sfConfig::get('sf_web_dir') . sfConfig::get('app_paths_docPdf') . $this->getFilename()), true);
$response->setHttpHeader("Content-Disposition", "attachment; filename=\"". $this->getFilename() ."\"");
$response->setHttpHeader('Content-Transfer-Encoding', 'binary', true);
$response->setHttpHeader("Content-Description","File Transfer");
$response->sendHttpHeaders();
$response->setContent(readfile(sfConfig::get('sf_web_dir') . sfConfig::get('app_paths_docPdf') . $this->getFilename()));
return sfView::NONE;
}
This works just fine for me in IE6,IE7, Chrome, Firefox.
Hope this will help someone.
As pilif already mentions, make sure to turn off the server-side gzip compression. For me this has caused problems with PDF files (among other types) and for maybe-not-so-obscure reasons also with .zip files both under Internet Explorer and FireFox.
As far as I could tell, the last bit of the zip footer would get stripped (at least by FireFox) causing a corrupted format.
In PHP you can use the following code:
ini_set("zlib.output_compression",0);
The following bit of Java code works for me (tested on Firefox 2 and 3, IE 6 and 7):
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
response.setContentType(getServletContext().getMimeType(file.getName()));
response.setContentLength(file.length());
No other headers were necessary at all.
Also, I tested this code both with gzip compression on and off (using a separate servlet filter that does the compression). Doesn't make any difference (works without any problem in the four browsers I tested it on).
Plus, this works for other filetypes as well.
You can add an additional parameter that the server won't read to the url it might help too.
http://www.mycom.com/services/pdf?action=blahblah&filename=pdf0001.pdf
I have run into cases where ie will be more likely to read the filename on the end of the url than any of the headers
I had a similar problem, but it might not be exactly related. My issue was that IE6 seems to have a problem with special characters (specifically slashes) in the file name. Removing these fixed the issue.
If you are using SSL:
Make sure you do not include any cache control (or Pragma) headers. There is a bug in IE6 which will prevent users from downloading files if cache control headers are used. They will get an error message.
I pulled my hair out over this for 2 days, so hopefully this message helps someone.
simply switch to this content type and it will work, also be sure Pragma ist set to something NOT equal "no-cache"
header( 'Content-type: application/octet-stream'); # force download, no matter what mimetype
header( 'Content-Transfer-Encoding: binary' ); # is always ok, also for plain text