1

I would like to compress a directory using 7-Zip and then download it to a web browser.

However, instead of compressing to a file, then having PHP feed the contents of that file to the browser... I would ideally like to Have 7-Zip write the contents of the new archive to standard output as the archive is being created... While simultaneously having PHP flush its buffer and and send the data to the browser.

You see, the archive I'm creating is quite large. From a user's perspective, using the normal method, when they click "Download," the archive is first created and saved to a file (which can take ~ 10 minutes), and only then is the file then fed up by PHP to be downloaded. What I am trying to do is combine both the archive and output steps into one single process.

Does anyone have any input on this?

Here is someone else on SourceForge who is trying to do the same thing...

http://sourceforge.net/projects/p7zip/forums/forum/383043/topic/3828566

=======

Thank you for all help. I am going to close this thread, as I have recently discovered an excellent discussion on this topic already exists on StackOverflow. See:

LAMP: How to create .Zip of large files for the user on the fly, without disk/CPU thrashing

=======

This is the final solution I went with, and it is working fantastic for me. Note that I am using the "InfoZip" program, which you can find for pretty much any platform.

header('Content-Type: application/zip');
header('Content-disposition: attachment; filename="file.zip"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');

passthru("zip -8 -q -r - ./some_directory | cat");
Community
  • 1
  • 1
tambler
  • 2,889
  • 2
  • 21
  • 25
  • Try set the archive as `dev/stdout`? (assuming linux) – moinudin Jan 04 '11 at 16:54
  • Does the 7za executable sends the compressed data to it's stdout? You need to get that first. – Savageman Jan 04 '11 at 17:04
  • Doing the following: "7za a -lr -mx0 -so ./davedir/" results in: "Error: I won't write compressed data to a terminal." – tambler Jan 04 '11 at 17:05
  • that's because you're not piping the results anywhere. It has the -so option for a reason though. It's just smart enough not to spit it out and fill up your screen with garbage. The passthru function in php ought to pipe the stdout away from 7z and allow it to function. Its worth a try. – ehudokai Jan 04 '11 at 17:13
  • possible duplicate of [On-the-fly zipping & streaming of large files, in PHP or otherwise](http://stackoverflow.com/questions/4357073/on-the-fly-zipping-streaming-of-large-files-in-php-or-otherwise) – tambler Jan 04 '11 at 17:37

3 Answers3

1

You could try running 7z using passthru with the -so (write data to stdout) option.

As long as you are sending download headers and content-type headers for 7zip mime types, I believe it will work.

Example

<?php
$filename = "somefile.7z";
$contentType = "application/x-7z-compressed";
header("Content-type: ".$contentType); // tell the browser your sending a 7zip file
header("Content-Disposition: attachment; filename=\"".$filename."\""); // use 'attachment' to force a download
passthru('/path/to/7z a -so <fileOrDirToBe7Zipped>');
?>

Hope that helps!

ehudokai
  • 1,878
  • 12
  • 9
  • When I do this: "7za a -so ./davedir"... I get this: "Error: I won't write compressed data to a terminal." Can I expect this to not work when run from the terminal, but to succeed when via PHP's passthru function? – tambler Jan 04 '11 at 17:15
  • On your commandline, what happens if you simply try "7za a -so './davedir' > davedir.7z – ehudokai Jan 04 '11 at 17:47
  • 1
    @tambler your right, 7za doesn't seem to output to stdout despite the -so option. Ugh... Is there a reason you have to use 7z, and not another compression method? – ehudokai Jan 04 '11 at 17:55
  • I just posted the final code I started using. It is working fantastic so far. – tambler Jan 04 '11 at 19:40
  • I've tried with 7z v9.20 under Linux. It fails with following error: `7z a -so / > /dev/null Creating archive stdout System error: E_NOTIMPL` – dma_k Apr 22 '12 at 19:28
1

This is the final solution I went with, and it is working fantastic for me. Note that I am using the "InfoZip" program, which you can find for pretty much any platform.

header('Content-Type: application/zip');
header('Content-disposition: attachment; filename="file.zip"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');

passthru("zip -8 -q -r - ./some_directory | cat");
tambler
  • 2,889
  • 2
  • 21
  • 25
-1

This is either not going to work or it will be horribly buggy. The web doesn't really work like this -- many browsers won't be able to correctly deal with an incomplete file (which is what they're going to be getting). Why not display a "Your file is being generated! We will email you a download link when it is finished." message, or a "Please wait, we are generating your file. This could take several minutes." message, along with a progress meter?

asthasr
  • 8,326
  • 1
  • 27
  • 39
  • I was just attempting to come up with a more elegant solution, but we may just have to do that if this really won't work. – tambler Jan 04 '11 at 16:56
  • 1
    why not? This method works just fine when generating your page, and taking output from 7zip as it is working should work as well. He isn't sending an incomplete file, he is sending it as it is being generated. That is of course, assuming 7zip writes the file from beginning to end, which I believe is part of the question here. Please clarify. – Brad Jan 04 '11 at 17:05
  • 1
    Yes. My intention is to have 7zip compress a directory and have PHP flush the data to the browser as it is generated... from beginning to end. – tambler Jan 04 '11 at 17:08
  • I may be wrong, but it's going to be a strange and unintuitive experience for the user even if it works -- a download without a 'progress' measurement which lasts for 10 minutes or more. I would also expect some browsers to poll the size of the file and end up stopping when it reaches that length, resulting in a corrupt/incomplete file. It just seems like you're putting in a potential point of failure here to no real gain. – asthasr Jan 04 '11 at 17:15