PHP tip: How to make a file downloadable through your script
October 10, 2008 – 11:46 am Tags: PHP, Zend FrameworkThis seems to be a relatively common question on #zftalk nowadays, so here’s a quick wrapup!
The traditional plain-PHP way
$file = file_get_contents('some.zip'); header('Content-Type: application/zip'); header('Content-Disposition: attachment; filename="some.zip"'); header('Content-Length: ' . strlen($file)); echo $file;
The Zend Framework controller way
//this is inside an action in one of your controllers: $file = file_get_contents('some.zip'); $this->getResponse() ->setBody($file) ->setHeader('Content-Type', 'application/zip') ->setHeader('Content-Disposition', 'attachment; filename="some.zip"') ->setHeader('Content-Length', strlen($file)); //If using Zend_Layout, we need to disable it: $this->_helper->layout->disableLayout(); //Disable ViewRenderer: $this->_helper->viewRenderer->setNoRender(true);
Subscribe!












8 Responses to “PHP tip: How to make a file downloadable through your script”
Here’s a short explanation of what the ZF code does:
the getResponse method returns the response object, which contains the headers and the data that will get sent to the user.
So, we simply use the setBody method, which will set the body (the data) of the response, and the setHeader method, to modify the response to suit our needs.
You could use the plain-PHP snippet with ZF and append exit; in the end to prevent any other output, but if you ever needed to unit test or something, it would cause problems. Using the response object, we can easily test its contents and headers.
By Jani Hartikainen on Oct 10, 2008
Informative.
I was about to make such a post on my blog. I think you published it after yesterday’s conversation on #zftalk.
By Sudheer on Oct 10, 2008
This is ugly - it breaks HTTP resuming, breaks caching.
Instead of very problematic (esp. in IE) Content-Disposition you could use mod_rewrite or /file.php/file.zip trick.
By kL on Oct 10, 2008
I don’t see how this differs from using file.php/file.zip, if that’s simply a PHP script which sends you the file. Also, Content-Disposition works perfectly well at least from what I’ve tested it.
Perhaps you should explain your comment better next time.
By Jani Hartikainen on Oct 11, 2008
In my opinion file_get_contents is the total wrong way for handling any kind of downloading files, it will consume a lot of memory, and if the file is bigger than memory_limit, it will break the script.
If someone wants to handle file-downloads through php, it should a least support resuming and I think using Zend_View is even in an Zend Framework Enviroment the wrong way, because it forces sending all content in one step, no chance for reading and sending data from a source in a loop.
By robo47 on Oct 11, 2008
That’s a good point. Using filesize() and fpassthru() are probably better options if your files are bigger - though you can’t use the response object “correctly” with fpassthru, unless you use output buffering, which would make it equal file_get_contents and nullifying the advantages it has
By Jani Hartikainen on Oct 11, 2008
I found mod_xsendfile a good solution to the readfile/file_get_contents dilemma. Just send the standard headers along with X-Sendfile and it handles with file transfer. Definitly worth a look…
By Tom Graham on Oct 11, 2008
file_get_contents? Seriously?
Web applications are practically front-ends. They run some instructions in the back. You run some Apache threads, each thread is manageable, you get a reasonably performant system. Start loading entire files into memory, you then have to unload them, and your thread is busy for that process. Caching is a real pain too.
A file should not be downloadable through a script. Create a symlink on the fly, or maybe do some socket business (in Python?) and create a mini-app to handle it. But PHP scripts are not here to serve files over HTTP; that’s what web servers are for.
By Josh on Oct 27, 2008