invalid Zip file downloads (header+php) - php

I try download a zip file via header:
$file = '/srv/users/serverpilot/apps/elm/public/dll/files/438de5/file-c117c93c.zip';
$filename = 'file-c117c93c.zip';
if (file_exists($file))
{
$fileName = trim($filename);
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename='.$fileName);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
file will download with true size. but when I open downloaded file, zip file can not be open (invalid archive error)
what is the wrong?

After trying several solutions I realized the problem is on the Content-Encoding: gzip sent by apache. My httpd.conf is set to send this headers by default and this causes a problem on file downloads:
HTTP/1.1 200 OK
Date: Mon, 02 May 2016 21:52:08 GMT
Server: Apache
x-powered-by: PHP/5.3.3
content-transfer-encoding: Binary
Content-Disposition: attachment; filename="peace.zip"
Vary: Accept-Encoding
Content-Encoding: gzip
Connection: close
Transfer-Encoding: chunked
Content-Type: application/zip
On a different server, the returning header doesn't contain Content-Encoding: gzip and your code works flawlessly.
HTTP/1.1 200 OK
Date: Mon, 02 May 2016 21:57:43 GMT
Server: Apache/2.2.15
x-powered-by: PHP/5.4.45
Content-Description: File Transfer
Content-Disposition: attachment; filename="peace.zip"
content-transfer-encoding: binary
Expires: 0
Cache-Control: must-revalidate
Pragma: public
Content-Length: 627874
Connection: close
Content-Type: application/zip
Solution:
I've struggle for about 1 hour with this...
Add the following at the beginning of your php file:
apache_setenv('no-gzip', 1);
ini_set('zlib.output_compression', 0);
Voilá, force download works...

Related

force pdf download on openshift with php

I have an application written in php using the Yii framework and hosted on Openshift. I need to force the download of a pdf file, created with mpdf (using this extension http://www.yiiframework.com/extension/pdf/).
On my local server, the following line suffices to force the download with the name I want:
$mPDF1->Output($file_name , 'D');
On Openshift, however, the download is not forced and the name of the file is not correct.
This is the code from mpdf that I think it is used to create the headers of the response:
else if ($dest=='D') {
header('Content-Description: File Transfer');
if (headers_sent())
$this->Error('Some data has already been output to browser, can\'t send PDF file');
header('Content-Transfer-Encoding: binary');
header('Cache-Control: public, must-revalidate, max-age=0');
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream', false);
header('Content-Type: application/download', false);
header('Content-Type: application/pdf', false);
header('Content-disposition: attachment; filename="'.$name.'"');
}
These are the response headers I get on my local server:
HTTP/1.1 200 OK
Date: Tue, 07 Jul 2015 07:15:34 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.9
Expires: Sat, 26 Jul 1997 05:00:00 GMT
Cache-Control: public, must-revalidate, max-age=0
Pragma: public
Content-Description: File Transfer
Content-Transfer-Encoding: binary
Last-Modified: Tue, 07 Jul 2015 07:15:34 GMT
Content-disposition: attachment; filename="invoice.pdf"
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/pdf
And these are the response headers I get on Openshift:
HTTP/1.1 200 OK
Date: Tue, 07 Jul 2015 07:05:05 GMT
Server: Apache/2.2.15 (Red Hat)
Expires: Sat, 26 Jul 1997 05:00:00 GMT
Cache-Control: public, must-revalidate, max-age=0
Pragma: public
Content-Description: File Transfer
Content-Transfer-Encoding: binary
Last-Modified: Tue, 07 Jul 2015 07:05:07 GMT
Content-Type: application/pdf
Vary: Accept-Encoding
Content-Encoding: gzip
Keep-Alive: timeout=15, max=99
Connection: Keep-Alive
Transfer-Encoding: chunked
So on Openshift it is missing:
Content-disposition: attachment; filename="invoice.pdf"
and the file is not downloaded but shown in the browser.
What can I do to make it work?
I think it will work if You remove Content-Type: application/pdf. Some browsers automatically open this kind of documents. Leave only application/octet-stream.
header('Content-Transfer-Encoding: binary');
header('Cache-Control: public, must-revalidate, max-age=0');
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
header('Content-Type: application/octet-stream');
header('Content-disposition: attachment; filename="'.$name.'"');
i'm using this after generating PDFs from a library. So far no problem.
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="generated.pdf"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($file_to_save));
header('Accept-Ranges: bytes');
readfile($file_to_save);
where $file_to_save is the absolute path of your pdf

PHP can't display image using X-SendFile and jpeg headers

For some reason I can't get the image to display properly, its chucking out errors not telling me what’s wrong, any ideas?
CODE
$finfo = finfo_open(FILEINFO_MIME_TYPE);
header("Content-type: ".finfo_file($finfo, $filepath));
finfo_close($finfo);
header('Content-length: '.filesize($filepath));
header('Content-Disposition: inline; filename="'.$file.'"');
header('X-Sendfile: ' . $filepath );
HEADERS
HTTP/1.1 200 OK
Date: Mon, 07 Apr 2014 13:45:37 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.10
X-Sendfile: /path/image.jpg
Content-Length: 0
Content-Disposition: inline; filename="image.jpg"
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
Content-Type: image/jpeg
Are you sure your file is there?
I see Content-Length: 0. I doubt you want to send empty file.
Try to remove headers output and replace it with echos to see where your scrit fails.
The above code did work, it was x-sendfile which was not configured properly in apache

PHP header isn't modifying the content/type

I can't get php to set various headers when trying to return a file.
Relevant code:
if (ob_get_contents()) ob_end_clean();
header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
header('Content-Type', 'application/pdf');
if (ob_get_contents()) ob_flush();
header('Content-Disposition', 'attachment; filename="' . basename($setfile) . '"');
header('Content-length', filesize($fullpath));
readfile($fullpath);
File exists, all is well. but the header response is always:
HTTP/1.1 200 OK
Date: Sat, 09 Nov 2013 22:19:22 GMT
Server: Apache/2.2.24 (Unix) DAV/2 PHP/5.5.0 mod_ssl/2.2.24 OpenSSL/0.9.8y
X-Powered-By: PHP/5.5.0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 20
Content-Type: text/html
I can modify the status code, i've returned 404 etc.. but the content-type is always text/html... I'm at a bit of a loss.. The content-disposition isnt being set.. hmm...
Serving the file requires a valid session, so please no 'just redirect to the file' type answers.
Thanks for any input
You are calling header() incorrectly. You want
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="' . basename($setfile) . '"');
See http://php.net/manual/en/function.header.php
what about this :
<?php
// We'll be outputting a PDF
header('Content-type: application/pdf');
// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="YOUR_FILE.pdf"');
#rob is right, you are calling header incorrectly. also, see if you are actually able to read the file.

Header Location + Content Disposition

So I have a downloads page where you click a link, it opens /downloads/download/randomhash
randomhash is found in the db, i increment a download counter, and then redirect to the actual file e.g. /uploads/2012/file.png.
Everything works except for the redirect doing what I'd like it to do. I'm not sure why it's not working...
header("Location: " . $row->uri);
header("Content-Disposition: attachment; filename=$row->name");
On the first load of the file, it has the appropriate content-disposition header (in firebug), but it doesn't prompt the file to be downloaded (which it should, right??). Any ideas?
Response Headers:
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0, public
Connection: Keep-Alive
Content-Disposition: attachment; filename=promotion_photo_2.jpg
Content-Encoding: gzip
Content-Length: 20
Content-Type: text/html; charset=utf-8
Date: Mon, 27 Feb 2012 01:01:22 GMT
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Keep-Alive: timeout=5, max=100
Location: /uploads/2012/mediakitD3CF.jpg
Pragma: no-cache
Server: *
Vary: Accept-Encoding
X-Powered-By: *
X-UA-Compatible: IE=Edge,chrome=1
You are setting the Content-Disposition header in the same response which tells the browser where to redirect. My suggestion is to just stream the attachment on the response, with no redirect
header('Content-Disposition: attachment; filename=file-to-be-downloaded.jpg');
header('Content-type: image/jpeg'); // or what is relevant, ie application/octet-stream
$fn=fopen("path-to-file/file-to-be-downloaded.jpg","r");
fpassthru($fn);

Clicking "Back" button from a page showing a PDF in Firefox and Chrome causes header to appear in the <body> tag

I'm running into a very strange error in Firefox and Chrome. The error doesn't occur in Safari. I'm displaying a PDF on a page with the following code (works fine):
header('Content-Length: ' . filesize($pdfPath));
header('Content-Type: application/pdf');
header('Content-Transfer-Encoding: binary');
header('Content-Disposition: inline; filename="' . $pdfId . '.pdf"');
readfile($pdfPath);
The PDF loads up beautifully, but when I click the back button in the browser (Firefox and Chrome), the page that I jump back to has the HTTP header included in the body tag.
HTTP/1.1 200 OK Date: Tue, 08 Mar 2011 00:18:47 GMT Server: Apache/2.0.63 (Unix) PHP/5.2.13 DAV/2 mod_ssl/2.0.63 OpenSSL/0.9.7l X-Powered-By: PHP/5.2.13 Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Content-Length: 7010 Keep-Alive: timeout=15, max=92 Connection: Keep-Alive Content-Type: text/html
This header is for the current page (not the page that displayed the PDF). In debugging, I printed out the body tag with the following jQuery code:
console.log($('body').html());
The header appears before any other content in the body. Any ideas as to what could be causing this rogue header to appear?
Finally figured out what was going on, and the fix was quite simple. I just added an exit() after the readfile(), so the final code ended up looking like this:
header('Content-Length: ' . filesize($pdfPath));
header('Content-Type: application/pdf');
header('Content-Transfer-Encoding: binary');
header('Content-Disposition: inline; filename="' . $pdfId . '.pdf"');
readfile($pdfPath);
exit();

Categories