download zip files in php using headers - php

I have following PHP Script for downloading the zip files:
header("Content-length:".filesize($archive_file_name));
header('Content-Type: application/zip'); // ZIP file
header('Content-Disposition: attachment; filename="downloadpackage.zip"');
header('Content-Transfer-Encoding: binary');
readfile($archive_file_name);
exit();
But it doesn't force the download the zip file instead, it shows the lots of unusual characters like below:
PK[�FA����#�X$D:\voice_06101243342pm014771957.wav�|�s]�y���b�CI\��{2m��M'�Eibu2\#B��܋{� 6b# $H,\#��:��Z�(q�����ә���Y��q�����,� ���� d��y��O�tp$PĽg��w}��}�r֯[7�u�"w���|o�7/Z��ˋ^Z������Ң�ZTZ\S|N����c�X8��c�X8��c�X8��c�X8��c�X8���۲,��a�oA*=ە���do:��|ˉ'rb�|�L2�*^�:q׵}/��\�s�Z?��G�[��=ϗ?
I have also placed the below code before the headers function :
if (headers_sent())
{
// HTTP header has already been sent
return false;
}
// clean buffer(s)
while (ob_get_level() > 0)
{
ob_end_clean();
}
This ignore to display those character and zip is also not force to download. I couldn't figure out the problem, please help me, it will be greatly appreciated.

PK[�FA����#�X$D:\voice_06101243342pm014771957.wav�|
�s]�y���b�CI\��{2m��M'�Eibu2\#B��܋{� 6b#
$H,\#��:��Z�(q�����ә���Y��q�����,� ���� d��y��O�tp$PĽg��w}��}
�r֯[7�u�"w���|o�7/Z��ˋ^Z������Ң�ZTZ\S|N����c�X8��c�X8��c�X8��c�X8��c�X8���۲,��a�oA*
=ە���do:��|ˉ'rb�|�L2�*^�:q׵}/��\�s�Z?��G�[��=ϗ?
This is your zip file.
You are a receiving a zip file and there's nothing wrong, you just need to correct your php processing script because apparently it is processing it as plain text/string.
Note the PK at the start, zip files start with 'PK` data. Test yourself by opening any zip file with a hex editor.

Try to add this to your header:
header('Content-Description: File Transfer');

Here is the simple function I use to download files:
function _download ($file_name) {
$src = fopen($this->download_path . $file_name,'r') or die("\n\n ========= Could not download $file_name\n");
$dest = fopen($file_name,'w');
stream_copy_to_stream($src, $dest);
}

Related

PHP Download - File emty [duplicate]

The end goal is for the user to download a .csv file. Right now I'm just testing trying to download a simple text file: test.txt. The only thing in this file is the word "test".
Here is the HTML code for files_to_download.php
Test file: <a href='test.php?file=test.txt'>Test.txt</a>
Code for test.php:
if(!(empty($_GET["file"])))
{
$file_name = $_GET["file"];
$path = "path/to/file";
$fullPath = $path . $file_name;
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: inline; attachment; filename=\"$file_name\"");
header("Content-Type: text/plain");
header("Content-Transfer-Encoding: binary");
readfile($fullPath);
}
I've tried variations of the headers above, adding more and removing others. The above seem to be the most common recommended on this site.
I've also tried changing
header("Content-Type: text/plain");
to
header("Content-Type: text/csv");
and get same results: empty .txt or .csv file.
The files are not empty when I open them directly (file browser) from the server. I've checked the permissions of the files and they're both 644, so the entire world can at least read the files. The directory is 777.
Is there a configuration on the Apache server I need to specify that may not be or am I missing something above.
Thanks for looking!
In most cases the path is wrong
Read the text file, then echo the text out after your header() calls.
Here's how I have my csv download set up:
//downloads an export of the user DB
$csv = User::exportUsers();
header('Content-disposition: attachment; filename=userdb.csv');
header('Content-type: text/csv');
echo $csv;
Where exportUsers() creates the csv data. You can easily just replace $csv with the contents of your text file, then echo it out.
And as far as your text file, you can use file_get_contents() to get the contents of your file into a string. Then echo that string.
Try setting the content length of the file:
header('Content-Length: ' . filesize($file));
Also, please have this in mind: file inclusion
In my case, the path was correct. And the download-forcing was working on windows, but not mac.
I figured out after few tests that the header Content-Length was failing. I was using the function filesize on a full url, like :
$url_my_file = "http://my-website.com/folders/file.ext";
header('Content-Length: '.(filesize($url_my_file)));
I replace it by
$url_my_file = "http://my-website.com/folders/file.ext";
$headers = get_headers($url_my_file, 1);
header('Content-Length: '.($headers['Content-Length']));
And ... It's working now :)

AutoDownload a file with PHP

I'm doing a little script that convert a csv to json with php.
I would like that, when you upload the file and the conversion is done, the converted file is automatically downloaded
exec(/*some stuff*/); // i call the script that convert the csv into json, i get my converted file path back
chmod($newFilePath, 0777); // i give all access to the new file
startDownload($newFilePath); // i ask the autoDownload
And here is the download function
function startDownload($path){
if (file_exists($path)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($path));
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($path));
readfile($path);
exit();
}
}
If I echo readfile($path); or filesize($path) I got the file content (which is exactly want i want) and the good informations, and I'm sure the path is correct. But when i execute the script nothing happens.
I'm probably missing something dumb ^^
How can I make the user download this json file?
I tried to make a link and he do the same, is this a problem of access or something like that?
EDIT :
I tester this script in Local, it works perfectly, so the problem is from the permissions or something like that. I'm really bad with this kind of stuff, so if you have some idea that could help ^^
Thx for the help!
Missing semicolon after exec :
exec(); // i call the script that convert the csv into json, i get my converted file path back
chmod($newFilePath, 0777); // i give all access to the new file
startDownload($newFilePath); // i ask the autoDownload
I woul'd check if chmod has really changed the path permission:
if(chmod($newFilePath, 0777)){
startDownload($newFilePath);
}else{
die('Permission denied');
}

Downloading a csv as a zip

Im using Php (Zend Framework) to download a datagrid as CSV..the csv generation works fine.I just want to know is it possible to download the csv file within a zip file
My current code
public function downloadCsvAction(){
header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=answers_csv.csv");
header("Pragma: no-cache");
header("Expires: 0");
echo "stuff1" . ",";
echo "stuff2".",";
//----bla bla
exit;
}
By calling the url controller/downloadCsv im getting a popup to save the csv.I want the csv to be in a zip file
Here is a simple code to zip and output csv as a zip file
//here is your csv file
$csvFile = "test.csv";
//location for php to create zip file.
$zipPath = "/tmp/$csvFile.zip";
$zip = new ZipArchive();
if ($zip->open($zipPath,ZipArchive::CREATE)) {
$zip->addFile($csvFile, $csvFile);
$zip->close();
//Make sure the zip file created and output it.
if(is_file($zipPath)){
header('Content-type: application/octet-stream; charset=utf-8');
header('Content-Disposition: attachment; filename="'.$csvFile.'.zip"');
header('Content-Length: ' . filesize($zipPath));
readfile($zipPath,false);
}
}
I just want to know is it possible to download the csv file within a zip file
Yes it is possible. Just create a ZIP-file and put the CSV-file in there. Then deliver the ZIP-file.
If you're looking for more technical info, please read into the related Q&A material as the concrete code differs highly on what you need to achieve:
Generating ZIP files with PHP + Apache on-the-fly in high speed?

ZIP Archive sent by PHP is corrupted

I am using php ZipArchive to create an zip file on-the-fly and send it back to the user. I temporarily store the zipped file in a folder above document root and then send it back with the code
header('Content-type:application/zip');
header('Content-Disposition: inline; filename="'.("file.zip").'"');
header("Content-Transfer-Encoding: binary");
header("Content-Length:".filesize($file));
$fh = fopen($file,'rb');
fpassthru($fh);
after having first issued a
$zip->close()
to ensure that that the file isn't open. The issue I have run into is this - the stored zip file is a valid archive which I can open in Windows 7, 7Zip, WinZIP etc. However, when I send the file down with the code above it ends up with an 0xD 0xA pair at the start of the file which is enough to render it corrupt. I cannot figure out where those characters could be coming from. Is this a known bug with fopen/fpassthru? Any help would be much appreciated.
I found when removing the header("Content-Length:".filesize($file)); line it fixed my very same problem...
After many tries to download zip file, the solution was:
$result = create_zip($files_to_zip,$fileZip,true,$path_parts['dirname']);
ob_clean();
ob_end_flush(); // more important function - (without - error corrupted
zip)
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header('Content-Type: application/zip;\n');
header("Content-Transfer-Encoding: Binary");
header("Content-Disposition: attachment; filename=\"".basename($fileZip)."\"");
readfile($fileZip);
unlink($fileZip);
exit();
What does your full script look like?
Generally speaking you should remove any closing PHP tags at the end of your script files, as it's probably output coming from the end of your script, or an included script.
Thank you #_on !
You helped me with this information.
But instead of removing header ("Content-Length:". Filesize ($ file)) ;, I inserted a line break "\\n", leaving:
header ("Content-Length:". filesize ($ file). "\\n");
And the file generated its size to assist in the download
Okay then.
Tks

PHP generated Excel file is different when downloaded

I have a PHP file that generates xls files using the module found at http://pear.php.net/package/Spreadsheet_Excel_Writer/
I can create the sample document just fine and when I open it, it looks fine.
My next step it to turn it into a downloadable link. To do that, I did this:
$mimeType = "application/vnd.ms-excel";
$file_name = "test.xls";
$file_path = "/tmp/".$file_name;
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header('Content-Type: application/' . $mimeType);
header('Content-Length: '.$size);
header("Content-Disposition: attachment;filename=$file_name ");
header("Content-Transfer-Encoding: binary ");
// open the file in binary read-only mode
// display the error messages if the file can´t be opened
$file = & fopen($file_path, 'rb');
if ($file) {
// stream the file and exit the script when complete
fpassthru($file);
exit;
} else {
echo $err;
}
When I download the file however, it contains a lot of garbage data both in Excel and OpenOffice. The diff says that then binary file in the /tmp folder and the downloaded file are different from each other. I'm guessing that it has something to do with the headers or with fpassthru but I haven't had much luck with debugging the issue.
Any ideas on what the problem is?
The multiple Content-Type headers are uncessary. You're essentially saying that the file is a muffin and a pizza and a ford taurus all at the same time. All you need is the application/octet-stream version, unless you want to serve up the exact mime type.
As well, is there any reason you're trying to turn the file handle returned by fopen() into a reference?
Try something simpler:
<?php
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment;filename=$file_name");
readfile("/tmp/test.xls");
exit();
?>
and see if that does any better.
Just make sure that you don't send ANYTHING out to the browser BEFORE the actual file content gets send.
It might just be some php 'error' or even 'notice' that Spreadsheet_Excel_Writer is producing and you don't even see. Or it might be a closing '?>' tag thats followed by s simple space or newline.
I had a similar error where the file that was generated inside the web folders were working. However the delivery using header('...') gave me corrupt files. This was due to a single space at the end of one php file after the closing '?>' tag.
I am using the same library and I just discovered that the files in the library itself are creating the whitespace.
Solution: In the following files remove the whitespace at the end of the file, or remove the ?> closing tag at the end.
Files to edit (all files in the Spreadsheet_Excel_Writer package):
Writer.php
Workbook.php
Worksheet.php
PPS.php
Parser.php
OLE.php
Parser.php
File.php
BIFFWriter.php
Validator.php
Root.php
Add the following code at the top of the page where the excel file is generated
ob_clean();
This would clear all the gibberish data.Also check for any echo statements.If echo statements are present, remove them. The data should always present in format specified by excel package.

Categories