I am a severe novice, but I did quite a lot of research before posting, so I hope you can help.
I'm trying to serve a large .zip file that is hosted on an Apache server, about 6.4 Gb. The file shows complete download in browser, but in fact only about 500Mb have been downloaded. This seems like a very common problem and have found a lot of other posts and information on the web, but the problem has been persistent for me.
Large Zip file offered for download using php
IE download incomplete even though it claims success
Large zip downloads failing only in IE
I have been testing with Chrome 39.0.2171.71, but I get the same problem with FireFox and IE. I think my file is much larger than what others have been posting about, therefore perhaps their solutions helped the situation, but didn't fix the root problem. I have a second .zip file that is about 400Mb, and I use the same http headers with success.
The most useful article I have found is this: http://perishablepress.com/http-headers-file-downloads/ and I have copied much of the php shown below from that source, as it appears other posters on this website have done.
I have also tried using X-SendFile, but I don't think my webhost has the appropriate Apache module installed. I've spent all day working on this, and have run out of ideas! I have used a download manager with success, I don't know if this was just by chance or what, but I don't want to require my clients to have to download and install a separate program just to get the .zip file.
<?php
// HTTP Headers for ZIP File Downloads
// set example variables
$filename = "huge.zip";
$filepath = "****";
// http headers for zip downloads
// header("X-Sendfile: $filepath$filename");
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"".$filename."\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filepath.$filename));
set_time_limit(0);
ob_end_flush();
#readfile($filepath.$filename);
?>
Here are the response headers when I run the php above
Remote Address:76.162.142.242
Request URL:****/GetSW.php
Request Method:GET
Status Code:200 OK
Request Headers
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Authorization:Basic ******
Connection:keep-alive
Cookie:_ga=GA1.2.1176828605.1417985823
DNT:1
Host:www.teamursa.org
Referer:http://www.teamursa.org/****.html
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
Response Headers
Cache-Control:public
Connection:Keep-Alive
Content-Description:File Transfer
Content-Disposition:attachment; filename="huge.zip"
Content-Length:6720560824
Content-Transfer-Encoding:binary
Content-Type:application/octet-stream
Date:Sun, 07 Dec 2014 22:16:57 GMT
Expires:0
Keep-Alive:timeout=3, max=120
Pragma:public
Server:Apache
X-Powered-By:PHP/5.2.17
You might need to increase the memory limit on the server. Try the below just after the opening PHP tag
ini_set('memory_limit','16M');
And just keep increasing from 16M
I recommend you try using a web browser to download file directly, meaning you go to the address that file is stored at. E.g www.example.com/downloads/download.zip Hope this helps
Related
I am creating downloadable zip file, it works fine almost everywhere. But in Mozilla Firefox on save of this zip I get strange message that my_zip.zip is HTM file (sorry for the language, but I hope it is pretty understandable):
If I choose save option it will be saved as normal zip (no sign of HTM at all), but in "open as" section there are only programms for opening HTM
So, the question is How to make Firefox detect this zip as zip?
I am currently using this headers (set by PHP):
header('Content-Description: File Transfer');
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=$zipFileName");
header("Content-Transfer-Encoding: binary");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-store");
header('Pragma: no-cache');
header("Content-length: " . filesize($zipFileName));
readfile($zipFileName);
Already tried using header("Content-Type: application/zip"); , does not work; plus application/zip is not standart (as I read here in some headers related question).
I am using Mozilla Firefox v40.0.3, the php project is using Laravel 5.1 (I doubt it has anything to do with this)
UPDATE:
While trying different application\[format]s , I added a dump and die command after headers
//bunch of kosher headers here...
readfile($zipFileName);
dd(headers_list());//dumps and dies
And I get a zip type in download window. Then I figured out that after die or exit I will always get right download type of zip; Then I deleted all dump-and-die sections , but download type remains as zip. I have no idea what i have fixed by this manipulations.
I would love to have an explanation of this strange situation
A quick google search suggests the Content-Type seems to be the culprit
header("Content-Type: application/octet-stream");
Try setting it to application/x-zip-compressed ?
ALso the comments in this bug report may be useful: https://bugzilla.mozilla.org/show_bug.cgi?id=540900
I've set up a Download-Script with PHP on my server, which checks some details before letting the user download files via Apache (X-Sendfile). The Files are outside the Document-Root.
The code for downloading with Apache and the Module X-Sendfile is:
header("X-Sendfile: $fullpath");
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$link_file\"");
When using Apache and X-Sendfile i have a download-speed of 500 kB/s with my client. I also tested it with Apache and without X-Sendfile with the same file within the Document Root - same thing here!
So I tested downloading the same file, with the same client, the same infrastructure on both sides and the same internet-connection a few seconds later via PHP with readfile:
header("Pragma: no-cache");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/octet-stream");
header("Content-Length: ".(string)(filesize($fullpath)));
header("Content-Disposition: attachment; filename=\"$link_file\"");
readfile($fullpath);
This time the download-speed was 9.500 kB/s!
I repeated this test using both options more than a multiple times and the result was the same every time trying. The only difference besides the download-speed was a waiting time of a few seconds (depending on the size of the file which was downloaded), when trying with the PHP readfile method. When repeating the PHP readfile method instantly, the waiting time didn't appear again. Most likely because it was stored in the memory after the first time.
I'm using a professional HP Raid-System on the server, which has an average local Speed of 800 MB/s, so the reason for this can't be the Diskspeed. Also i didn't find any compressing- or bandwith-settings in the httpd.conf of Apache.
Can anyone of you explain why there is such a great difference of the download-speed and how this can be changed?
Thank you in advance.
Server: Windows Server 2008 R2 Apache/2.2.21 (Win32) PHP/5.4.20
Client: Windows 7 Ultimate x64 Google Chrome 30.0.1599.101 LAN >100 Mbit/s
SOLUTION:
httpd.conf, turn on the line "EnableSendfile off"
I use this http://phpexcel.codeplex.com/ to export to excel.
need to export 11000 - 65000 rows...
but when trying to do this browser hangs up.
it do not answer with errors or other messages. just show that request in progress.
top shows that apache finished work.
even apache log says that all done:
x.x.x.x - - [28/Jul/2011:12:28:38 +0300] "POST /doctor/lab/statistic/ HTTP/1.1" 200 2773504 "http://x.x.x.x:82/doctor/lab/statistic/" "Mozilla/5.0 (X11; Linux i686; rv:5.0) Gecko/20100101 Firefox/5.0"
but still no results.
system:
Linux Eearth 2.6.34-12-desktop #1 SMP PREEMPT 2010-06-29 02:39:08 +0200 i686
PHP Version 5.3.5
Apache/2.2.15 (Linux/SUSE)
so the question
EDIT 1
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="'.$filename.'.xls"');
header('Cache-Control: max-age=0');
$writer = PHPExcel_IOFactory::createWriter($xls, 'Excel5');
$writer->save('php://output');
exit;
EDIT 2
i tried to save data to file like this $writer->save('test.xls'); filesize 2.7MB
then if i do this:
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="'.$filename.'.xls"');
header('Cache-Control: max-age=0');
include 'test.xls';
exit;
download starts immediate...
It's possible that your web server is not emitting error messages, so I'd say check your error.log (should be hanging around in /var/log/apache2 or similar.) It might well be something trivial like not being able to write to a temporary file.
If that turns out as a dead-end, consider programmatically creating CSV files with echo statements - Excel will open those just fine.
EDIT
To produce CSV, do your headers
header('Content-Type: text/comma-separated-values);
header('Content-Disposition:attachment;filename="'.$filename.'.csv"');
header('Cache-Control: max-age=0');
Then output your column headers:
echo "col1,col2,col3,col4,..."
followed by a new line. Then output your data:
while(/*Still got some rows*/) {
echo $row[0] . "," .$row[1] "," + ...
}
Have a look at: http://en.wikipedia.org/wiki/Comma-separated_values, it's a really simple file format and Excel will open it without difficulty.
The other thing, which I hadn't thought of, is if you've got access to a Windows Server, you can produce Excel files directly via COM interop.
Can anybody tell me how we can delete browser cache using javascript. I want this because I am giving user, file for download with url ('http://www.example.com/docs/doc1.xlsx'). and this files are accessible for that specific user only.
I am checking with htaccess redirect to other action which redirect to that specific file url if user does not have access then Access Denied page come.
But problem is when valid user download that file and logs out from application and copied above url and hit enter on browser file gets for download without accessing to server, which happens due to caching in browser.
So I want to delete cache when user logs out of system.
Alternative solutions are most welcome.
In short, you can't (or, at least, I have never seen a way of doing it).
You'll need to do it on the server side by sending the correct cache-busting headers. Something like:
Cache-Control: no-cache, must-revalidate, max-age=0
You can do this using (to steal an example from the PHP documentation):
header("Cache-Control: no-cache, must-revalidate, max-age=0");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
This is not possible. Php only works serverside and using javascript is not working because of security issues. ActiveX is not an option eigther i guess.
What you can do is to attach a no-cache header for a page that must reload each time.
Rather than giving direct access to the file (as you mentioned "http://www.example.com/docs/doc1.xlsx"), I think you should read the the file in php and give it for download after checking for the valid user..
Example taken from php.net
<?php
// downloading a file
$filename = $_GET['path'];
/**
* YOU CAN CHECK YOUR VALIDATIONS HERE..
*
*
*
*/
// fix for IE catching or PHP bug issue
header("Pragma: public");
header("Expires: 0"); // set expiration time
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
// browser must download file from server instead of cache
// force download dialog
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
// use the Content-Disposition header to supply a recommended filename and
// force the browser to display the save dialog.
header("Content-Disposition: attachment; filename=".basename($filename).";");
/*
The Content-transfer-encoding header should be binary, since the file will be read
directly from the disk and the raw bytes passed to the downloading computer.
The Content-length header is useful to set for downloads. The browser will be able to
show a progress meter as a file downloads. The content-lenght can be determines by
filesize function returns the size of a file.
*/
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filename));
#readfile($filename);
exit(0);
?>
Hope this helps..
Thanks...
I have resolved issue without major modifications.
Firstly I tried by setting header as you people suggested. Before redirecting for file to download I tried to set header for cache-control, but it doesn't work at all.
So I stretch my mind more and find simple solution by setting headers in .htaccess file which is located in folder where all downloadable files are located. That means cache-control header is set to download files response.
But still one thing in mind why above solutions not working.
And one more thing Pragma: "no-cache" not working for IE. that is it gives error while downloading requested file as "requested site is unavailable or cannot be found".
So I have set it to Pragma: public. But I doubt whether it is secure.
I have just moved a web application to a windows server and having some problems. One of it is -
application stores list of names of files in a database table. when a files is requested for download it is sent to output by sending proper headers (depending upon mime type and then a readfile("document location/filename.extension");
it works fine in firefox but if I try to download in IE it throws
IE can not dowload this document from
www.mysite.com .. IE was unable to
open this Internet site. The requested
file is either unavailable or cannot
be found. Please try again later.
As it was working fine on previous server (non-windows), I tried to print document location and it read somewhat like C:/Apache/htdocs/FILENAME.ext and I guess this C:/ is causing problem in IE but not in firefox??
How do I get it working right in IE??
Thanks
UPDATE
I have got it working by
adding some more headers among others .. I think first 2 are more important for IE or so (atleast working for me for now :)
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
It works :
if (strstr($_HTTP_USER_AGENT, "MSIE")) {
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: doit-revalider, post-check = 0, pré-check = 0");
header("Content-Type: application de téléchargement; name=\"$sFilename\"");
header("Content-Length: $iTaille");
header("Content-Disposition: attachment; filename=\"$sFilename\"");
header("Content-Transfer-Encoding: binary");
} else {
header("Content-Type: application de téléchargement; name=\"$sFilename\"");
header("Content-Length: $iTaille");
header("Content-Disposition: attachment; filename=\"$sFilename\"");
}
this question had already been answered here PHP: Force file download and IE, yet again
Is this by any chance over SSL? If so, there are a whole host of bugs in MSIE which could be affecting your app. Try setting a very short caching time.
If it works on Firefox using the the same server, then the problem unlikely to be anything to do with the path on the server. Although beware that (IME) IIS seems to tunnel authorization from MSIE clients (but not others) in some instances.