Download .zip file problem (downloading .php file) - php

I want to download a .zip file, but when i go to download it, it forces me to download the .php file. I use this simple code that is all over the internet so I don't know why I can't download .zip file.
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Content-type: application/zip");
header('Content-length: '.filesize($fullpath));
header("Content-disposition: attachment; filename=".basename($fullpath));
readfile($fullpath);

If you are serving the PHP file with a .zip extension, getting the PHP source code for download is expected behaviour - ZIP files do not get parsed by the PHP interpreter by default.
You would have to register the ZIP extension to be parsed by PHP. That is pretty sub-optimal, though; in this case, you can link to the PHP file with the .php extension. The filename header will provide the correct name to the user who downloads the file.
If you are using a .php extension and the source code of your PHP file is served, your server configuration is broken.

I think you are downloading the zip file named as .php
try to open the downloaded file with winzip or winrar

Related

PHP file download not recognizing file type in Chrome and Edge

I'm trying to create a simple download page, which currently works in Firefox but not entirely in Chrome and Edge. The file to download is an mp3, located in a private directory on the server.
When I download the file in Firefox it works as intended. If I download it using Chrome or Edge the file still downloads, but it doesn't recognize the file type and just saves it as an extensionless file. If I add the .mp3 extension manually to the downloaded file it's fine and I can play the track.
These are the headers:
header("Cache-Control: private");
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Length: " . filesize($filePath));
//Force download
readfile($filePath);
Changing the 'Content-type' to 'audio/mpeg' also doesn't work.
can you try:
header("Content-Disposition: attachment; filename=\"$title\".mp3");
to see if the title does not contain the extension

PHP readfile() which preserves mime-type

I am trying to set up a PHP script which can pull files (for validated users) from a folder outside of the live webroot. The problem is that when doing this, even if I use a proper "Content-Type" header, the file is downloaded as application/octet-stream. This has security implications if the user later tries to re-upload the downloaded file as it will be detected as an application even when it is really a pdf (my application only allows certain mime-types to be uploaded).
This is what I am using to pull the file into the browser:
$secret_file = "../attach/1/test.pdf";
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
header("Content-Type: ".mime_content_type($secret_file));
header("Content-Disposition: inline; filename=\"test.pdf\";");
header("Content-Transfer-Encoding: binary");
readfile($secret_file);
Interestingly, if I download the file this way through a browser and view its properties in linux, it shows up as "application/pdf". However, if I check the same file using PHP's mime_content_type() function, it reads as application/octet-stream.
I did confirm that checking the original file this way (before it is pulled through readfile) shows it as application/pdf.
Is there any way to use readfile() without changing mime types? Or, is there perhaps a better alternative?
EDIT
Answering some questions from the comments:
Developer Tools in Firefox reports that the inline file has a Content-Type: application/pdf header.
sha256sum of downloaded file does not match the original file. But how could readfile() (or similar) be used without changing the file?

Download Excel file with PHP over https

I am about to take a web application I've been working on live and am now, of course, updating code to make things that worked perfectly on my localhost work on the secure server. One of the tasks this application performs is generating and downloading files. All of the files are being generated and written to the server, but the .xls, .csv, and .json files download with no data even though the data is in the files on the server. The .xml, .zip, and .sql files do download with accurate data. An .xls or .json file that is contained within a .zip file is fine. This problem is not IE specific as I am using Chrome. Also tried Safari with the same results.
Here is what I'm doing to download the Excel:
$excel_content = file_get_contents($download_file_name);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"".$file_name);
header("Content-Transfer-Encoding: binary");
header("Pragma: no-cache");
header("Expires: 0");
print chr(255).chr(254).mb_convert_encoding($excel_content, 'UTF-16LE', 'UTF-8');
Here is what I'm doing to download the XML:
$xml_content = file_get_contents($download_file_name);
header("Content-Type: application/xml");
header("Content-Disposition: attachment; filename=\"".$file_name);
header("Content-Transfer-Encoding: UTF-8");
header("Pragma: no-cache");
header("Expires: 0");
print $xml_content;
Can anyone see why the Excel works on my localhost, but not on my server through https protocol? If it matters, I do have openssl enabled as verified with an info.php file on the server.

PDF file not correctly encoded when downloading a pdf file from php

This might be a duplicate but I have searched for the solution for so long and I still could not solve my problem. I have a localhost server where it stored some pdf files for download.
I implemented the following function to force the download:
if(isset($_POST['dlPDF']))
{
$file = $_SERVER['DOCUMENT_ROOT'] .'/Upload/'.$pdfName;
header("Content-Type: application/pdf");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$pdfName");
header("Content-Transfer-Encoding: binary");
// read the file from disk
readfile($file);
}
However I could not open the pdf file properly since it says "the pdf file is not correctly encoded".
FYI, the downloaded pdf file is always a few Kb larger than the original file.
Please kindly let me know if there is anything I can do to make the pdf readable and I appreciate your help.

Creating and serving zipped files with php

I'm trying to use the following code to create a zip file from a directory and serve it to the user via an http download:
// write the file
file_put_contents($path . "/index.html", $output);
// zip up the contents
chdir($path);
exec("zip -r {$course->name} ./");
$filename = "{$course->name}.zip";
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' .urlencode($filename));
header('Content-Transfer-Encoding: binary');
readfile($filename);
I am able to create the zip file, but downloading it over http is not working. If I download the zip file that's created using an ftp client then Mac's Stuffit Expander unzips the files just fine, but if I download it over http, the mac unzipper creates an endless loop. What I mean by this is say the file I download is called course.zip, then unzipping the file gives course.zip.cpgz and unzipping that file gives course.zip again..and on and on.
Anyone have any ideas?
Thanks!
I had this problem and it turned out the downloaded zip file had a new line inserted at the very beginning.
Solved by using ob_clean and flush functions
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".basename($archive_file_name));
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($archive_file_name));
ob_clean();
flush();
echo readfile("$archive_file_name");
Re-zipping it every time it is requested is not a good idea. Try doing that only if the ZIP file does not exist already.
If is a volatile file or just a single small file you want to transfer compressed, try using ob_start('ob_gzhandler') instead, simplier, smaller, cleaner. The file is transfered compressed, but it is saved in its original format by the client-side.
Specifying the Content-Length header is needed to allow the downloader to know the end of the file, allowing progress control, detection of corruption of the file and avoiding the hang of the HTTP session (if Connection is in Keep-Alive mode), maybe the lack of this header is the root of the problem.
As suggested by karim79, I'll put my comment as an answer: what happens if you change the MIME type from application/octet-stream to application/zip?
Also, I see you're using a command line zip program, but you don't check for success of the zip, and also don't check if the file exists before attempting to send it out to the end users browser. Try hard coding a file name, manually using zip to guarantee a properly formed zip file, and then see if your code will spit it to your browser properly.
What you're seeing is that the archive utility is not recognizing the zip file as a zip file, and tried to zip up the zip archive itself. The second operation simply unzips the first file created, so never actually opening the file at all. This is due to the zip being corrupted.
It is possible that the browser somehow mangled the zip file (newline conversions anyone?) during the download process. As mentioned, check the mime type and use the php header() to set the correct MIME type (application/zip).

Categories