The builtin browser of my ebook-reader (Sony PRS-T1) somehow doesn't like to download .epub files.
Normally it opens .epub files as if they were text-files.
With this php-download-script I managed to force the browser to download files I store on my server:
<?php
$path = $_GET['path'];
$mimeType = $_GET['mimeType'];
if(!file_exists($path)) {
// File doesn't exist, output error
die('file not found');
} else {
$size = filesize($path);
$file = basename($path);
// Set headers
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-Disposition: attachment; filename=\"$file\"");
header("Content-Type: $mimeType");
header("Content-Transfer-Encoding: binary");
header("Content-Length: $size");
// Read the file from disk
readfile($path);
}
exit();
?>
Now, the PRS-T1 would download the file but for some reason I don't understand it will change the file extension from .epub to .htm - this is weird.
But it seems like there is a way to do it right: when I download a .epub file from readbeam.com it works just like expected (I found this hint at http://www.mobileread.com/forums/showthread.php?t=163466).
What is it, that makes the difference betweeen their configuration and mine?
Here's what I found out using firebug:
http://tinypic.com/r/vzzkzp/5
http://tinypic.com/r/2h7pbth/5
Your Content-Type header doesn't match the one from readbeam.
application/epub zip != application/epub+zip
The + is probably being seen by PHP as a space since it seems you are passing it via $_GET.
Related
I have a zip files that I want users to be able to download. The trick is I don't want the users to see what the url is and I don't want to download the file to my server.
So I want users to click a link like this:
http://example.com/download/4
which server-side accesses my S3 bucket with this url:
https://s3.amazonaws.com/my-bucket/uploads/4.zip
I've tried cURL, using S3 methods, and various headers() in my download($file_id) function but can't get this to work. This has to be easy, right?
Your right, its quite easy. Probably you will have to write something like this:
$path = '/my-bucket/uploads/4.zip'; // the file made available for download via this PHP file
$mm_type="application/x-compressed"; // modify accordingly to the file type of $path, but in most cases no need to do so
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: " . $mm_type);
header("Content-Length: " .(string)(filesize($path)) );
header('Content-Disposition: attachment; filename="'.basename($path).'"');
header("Content-Transfer-Encoding: binary\n");
readfile($path); // outputs the content of the file
exit();
You set various headers to make your user download the .zip. Afterwards you put your file into the output buffer with readfile() Afterwards you end your script with exit() for security's sake. This should work for you! Remember to change the path to your file.
Thanks #Xatenev for the help. This is actually what worked for me:
$path = '/my-bucket/uploads/4.zip'; // the file made available for download via this PHP file
$mm_type="application/zip"; // modify accordingly to the file type of $path, but in most cases no need to do so
header("Content-Type: " . $mm_type);
header('Content-Disposition: attachment; filename="'.basename($path).'"');
readfile($path); // outputs the content of the file
exit();
<?php
$file = $_GET['name'];
$path = './curr/'.$file.'.pdf'; // the file made available for download via this PHP file
$mm_type="application/pdf"; // modify accordingly to the file type of $path, but in most cases no need to do so
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: " . $mm_type);
header("Content-Length: " .(string)(filesize($path)) );
header('Content-Disposition: attachment; filename="'.basename($path).'"');
header("Content-Transfer-Encoding: binary\n");
readfile($path); // outputs the content of the file
?>
This is a snippet of code in file.php. I am referring to the file using:
File 1
The intent is that on click of the link, ./curr/First File.pdf should download. I do get a download, but on inspecting, it's the webpage with the pdf embedded in the file. Could anyone assist?
If you want to have just the PDF loaded, the above code is all code to be executed.
Drop all surrounding menus, header or footers. Make sure, that no HTML or any other output besides the PDF from readfile() remains, when calling this link.
Try to change the content type to :
header("Content-Type: application/force-download");
For reference, I have already read and tried the answers in these and several other threads:
Creating and serving zipped files with php
Opening downloaded zip file creates cpgz file?
I have a zip file on my server.
When I use Filezilla to move that Zip file from my server to my Mac, I can open it normally.
When I use this PHP code to download the Zip file to my Linux machine, it opens normally.
When I use this PHP code to download the Zip file to my Mac, using Safari or Firefox, I get an error saying "Decompression Failed" or "The structure of the archive is damaged" or I get a .cpgz file - which I believe means that the computer is zipping the file, not unzipping it.
Here is the PHP code I am using to deliver the zip file.
$zipname = "myfile.zip";
$zippath = "/path/to/" . $zipname;
if ($downloadzip = fopen ($zippath, "r")) {
$fsize = filesize($zippath);
header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=\"".$zipname."\"");
header("Content-length: $fsize");
header('Content-Transfer-Encoding: binary');
#header("Cache-control: private"); //use this to open files directly
echo fpassthru($downloadzip); // deliver the zip file
}
fclose ($downloadzip);
I found some headers that work. I don't really know or care why it work, I am just happy it works... I tried a ton of different things, .htaccess files, php.ini / zlib settings.
Here's the answer
http://perishablepress.com/http-headers-file-downloads/
$zipName = 'myfile.zip';
$zipPath = 'mydirectory/' . $zipName;
if (file_exists($zipPath)) {
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=\"".$zipName."\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($zipPath));
ob_end_flush();
#readfile($zipPath);
}
Often the issue is caused by extra characters that have been printed or echo'd to the page before you read out the file. Even a space will cause the failure. To fix that issue, call ob_end_clean(); before you read the file which will clear the output buffer and turn off buffering.
But keep in mind you can have nested output buffers, and this will corrupt your download as well (cheers to Vladamir for figuring this out). So to clear the output buffer completely run this before you read your file:
while (ob_get_level()) {
ob_end_clean();
}
This will clear out your entire buffer and you won't have any extra characters to mess up your download.
For those interested i've pasted my download script below. My zip files now download perfectly, and so far this works great.
if (file_exists($zip_file_path)) {
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");
//We can likely use the 'application/zip' type, but the octet-stream 'catch all' works just fine.
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename='$zip_file_name'");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($zip_file_path));
while (ob_get_level()) {
ob_end_clean();
}
#readfile($zip_file_path);
exit;
}
Here is what works
$zipName = 'myfile.zip';
$zipPath = 'mydirectory/' . $zipName;
if (file_exists($zipPath)) {
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=\"".$zipName."\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($zipPath));
ob_end_flush();
#readfile($zipPath);
}
Well, I presume you know that your $fsize variable is not being written to that header because it's enclosed by quotes.
You could try something like this:
header('Cache-Control: public');
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename=\"".$zipname."\"');
header('Content-Type: application/zip');
I have the following code to push a zip file for download.
$filename = "ResourcePack_".time().".zip";
$destination = $basepath."downloads/$filename";
if($this->createdownload($files,$destination,false)){
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Length: ". filesize("$destination").";");
header("Content-Disposition: attachment; filename='$filename'");
header("Content-Type: application/octet-stream; ");
header("Content-Transfer-Encoding: binary");
ob_end_flush();
#readfile($destination);
if(file_exists($destination)){
unlink($destination);
}
}
I know the createdownload function is working to generate the zip file just fine because I see the file being created on the server. The problem is file is being written to the browser as a bunch of garbage instead of opening a download stream. Am I missing something in my headers?
EDIT
I was right. My problem is not with the php, but that calling the php file that generates this code via a JQuery $.ajax call is the problem. Using $.ajax automatically sets the Accept-Encoding request header to values incompatible with zip files. So, intead of using $.ajax I just used a simple window.open javascript command to call the same php page and it works just fine with the headers.
try to put a die after the #readfile
and remove the #, to see if you have any other error related with the file reading.
i have some code doing the same thing and this works for me:
header("Pragma: public");
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-Disposition: inline; filename="' . $filename . '"');
header('Content-type: application/zip');
//header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($destination));
readfile($destination);
die();
try passing proper type for that file. I think its fileinfo mime type see http://www.php.net/manual/en/ref.fileinfo.php
header("Content-Type: $file_type");
Also you have semicolon after octet-stream remove it
header("Content-type: application/octet-stream");
What I am trying to implement is force download of a file through PHP.
There are 2 issues that I am facing, and I've broken my head thinking about what is possibly going wrong here.
Whenever I try to download the file using IE, the download gets interrupted about midway i.e. say my file is 1024Kb in size, around 500Kb is when the download stops as I get an error message in IE say 'Download was interrupted'
The other issue that I encounter frequently (but not always) is that the downloaded file (which is actually a zip file) gets corrupted at times for some reason! The file on the server is alright - if I download it directly from there, no issues at all. However, if I download using my PHP script and then try to unzip the file - Windows says 'Invalid or corrupt file...'
I really need some help on this.
Following is the block of code downloading the file:-
$fileName = "./SomeDir/Somefile.zip";
$fsize = filesize($fileName);
set_time_limit(0);
// required for IE, otherwise Content-Disposition may be ignored
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
// set headers
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/zip');
header("Content-Disposition: attachment; filename=\"".basename($fileName)."\";");
header("Content-Transfer-Encoding: binary");
header('Accept-Ranges: bytes');
header("Content-Length: " . $fsize);
// download
$file = #fopen($fileName,"rb");
if ($file) {
while(!feof($file)) {
print(fread($file, 1024*8));
flush();
if (connection_status()!=0) {
#fclose($file);
die();
}
}
#fclose($file);
}
Try this
<?php
$file = "./SomeDir/Somefile.zip";
set_time_limit(0);
$name = "Somefile.zip";
// Print headers and print to output.
header('Cache-Control:');
header('Pragma:');
header("Content-type: application/zip");
header("Content-Length: ". filesize($file));
header("Content-Disposition: attachment; filename=\"{$name}\"");
readfile($file);
?>
I think that your content-length reports more bytes than the amount really transferred.
Check in the server's log. The server could gzip the content and when it closes the connection the client is still waiting for the remaining declared bytes.