Page 1 of 1

downloading zip using php

Posted: Mon Apr 11, 2011 7:44 pm
by phplearner123
have been trying to set up an area in a registered user only area of a site, have found many scripts to start a download without showing the actual area where the file resides, but the one thing I can't seem to get fixed is getting the zip file which is downloaded either not to be corrupted or simply empty.
No matter what I try, it is always empty or corrupted.

here is the code which returns a zip without any content:

Code: Select all

<?php
ob_start();
$path = '/site/site_files/download_files/test.zip'; 
$mm_type="application/zip"; 

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).'"');
ob_end_clean();
readfile($path); // outputs the content of the file

exit();
?>
I thought the ob_start and the ob_end_clean would resolve this, but it really is a hassle for me.
This is the second time I've posted on these forums because I tend to google the answer, I much rather spend hours and hours trying and testing to resolve my problems rather than posting a noob question (designer with very basic php skills) and wasting the time of so many who help others, but in this case, I just can't seem to get that zip downloaded correctly.
I have tested on Linux, OSx, WIn, and every browser from IE7 to 9, current versions of FF, Op, Saf, Chrome all the same, the file downloads, it even extracts, but there isn't anything in it. I have made sure several times, the path is correct and that the zip actually DOES contain a test file. Have also tried to use http in the file path, does the same thing.
Any help, as always, is highly appreciated

Re: downloading zip using php

Posted: Mon Apr 11, 2011 9:28 pm
by gooney0
Well your ob_start and ob_end_clean are preventing the headers from being sent. You're buffering them but not outputting the buffer.

You'd need a ob_get_contents(); and an echo or print.

Re: downloading zip using php

Posted: Tue Apr 12, 2011 3:48 pm
by phplearner123
that's the problem, even on php.net, in one of the examples of a script which is simalar, it is noted that ob_start and ob_end_clean are needed for zips to work, now I am really confused, have looked at php.net again for ob_get_contents, but I am not sure how to implement it. And as for echo, if I am automatically starting a download, would I use that? I thought echo was to place content within the page itself.
I know you are right, because, actually it's any file which is downloaded, a jpg is a jpg, but without content, pdf, zip, etc. I just don't know how to implement it correctly. As I said, I came here as a last resort to get help from serious coders, though I can hold my own with html and css, php still eludes me, I apologize.

Re: downloading zip using php

Posted: Wed Apr 13, 2011 11:28 am
by gooney0
No problem here is a quick demo:

Code: Select all

// Capture output from here on down...
ob_start();
print "This won't actually be displayed until latter.";
// Save the buffered output into a variable.
$my_output=ob_get_contents();
// Stop buffering and clear the results from memory
ob_end_clean();

// Now let's print the variable
print $my_output;
Try the above example. If you don't print $my_output you won't get any output at all.

Here is some code I use for downloads...

Code: Select all

$relpath="/subdirectory/filename.zip";
		$shortfilename=substr(strrchr("$relpath", "/"), 1);
		// This is need for IE
		header("Cache-Control: cache, must-revalidate");
		header("Pragma: public");
		header("Content-Type: application/force-download");
		header("Content-Transfer-Encoding: binary");
		header("Content-Disposition: attachment; filename=\"".$shortfilename."\"");
		header("Pragma: no-cache");
		header("Expires: 0");
		readfile($_SERVER["DOCUMENT_ROOT"]."/"."$relpath");
		die();
In this code example the file to download is within the server's document root. You can adjust the paths as needed.

There is also no output at all other than the file being downloaded. You can't print or echo anything before using the "header" function.

Re: downloading zip using php

Posted: Wed Apr 13, 2011 9:21 pm
by phplearner123
gooney0 I appreciate you taking the time with helping my out, as you mention that there wont be any output just the file, I expected that an error on my part would return an empty zip, the simple print function worked, it ouput just fine, but here I am not sure where to place the print function, I thought the readfile was responsible for the output...noobs playing with php is dangerous! :roll: I hope I fixed the character codes correctly and that I didn't mess up your original syntax.

Code: Select all

<?php
ob_start();
$relpath="/site/site_files/download_files/test.zip";//the path is correct,"site" is a subfolder
$shortfilename=substr(strrchr("$relpath", "/"), 1);
header("Cache-Control: cache, must-revalidate");
header("Pragma: public");
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: binary");
header("Content-Disposition: attachment; filename=\"".$shortfilename."\"");
header("Pragma: no-cache");
header("Expires: 0");
$file_output=ob_get_contents();
ob_end_clean();
print $file_output;//obviously wrong area, just thought I would leave it so you could see
readfile($_SERVER["DOCUMENT_ROOT"]."/"."$relpath");
die();
?>
also does my original script I posted or yours post any security risks? I am so sorry, it's just that I have seen so many download scripts lately and tons of them had been flagged as being extremely dangerous, allowing a blackhat to download almost anything they wanted. we web designers really do have to pay our respects to those who can work the heavy code.

Re: downloading zip using php

Posted: Sat Apr 16, 2011 8:23 pm
by gooney0
Actually you got it right. You want to print the header information before readfile outputs the zip. $file_output is a bad name though. It's really $header_output. The file will be outputted using readfile().

readfile() will open and print the file all at once.

As for security you're alright so far. Where it would get dangerous is if you allowed the user to specify which file they wanted to download. You don't want users to download your code.

In this case they can only download the zipfile.