37

I have a file

/file.zip

A user comes to

/download.php

I want the user's browser to start downloading the file. How do i do that? Does readfile open the file on server, which seems like an unnecessary thing to do. Is there a way to return the file without opening it on the server?

hakre
  • 193,403
  • 52
  • 435
  • 836
barin
  • 4,481
  • 6
  • 28
  • 29

4 Answers4

102

I think you want this:

        $attachment_location = $_SERVER["DOCUMENT_ROOT"] . "/file.zip";
        if (file_exists($attachment_location)) {

            header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
            header("Cache-Control: public"); // needed for internet explorer
            header("Content-Type: application/zip");
            header("Content-Transfer-Encoding: Binary");
            header("Content-Length:".filesize($attachment_location));
            header("Content-Disposition: attachment; filename=file.zip");
            readfile($attachment_location);
            die();        
        } else {
            die("Error: File not found.");
        } 
Gabriel Spiteri
  • 4,896
  • 12
  • 43
  • 58
  • 4
    FYI: [What is the risk of having HTTP header “Cache-Control: public”?](http://stackoverflow.com/q/3339859/216084) –  Dec 10 '14 at 06:01
  • 1
    its work. Header for download with space in filename just add header("Content-Disposition: attachment; filename=\"".file.zip."\""); – sirmagid Jun 13 '17 at 13:36
  • 3
    You could just have ```header("Content-Type: application/octet-stream");``` to make this work with all file types instead of just ```.zip```. – Griffin Garman Jan 19 '20 at 22:25
  • please anyone can support I used the same code but it opens the file in the browser instead of downloading it – Ibrahim Tayseer Mar 10 '20 at 23:46
2

readfile will do the job OK and pass the stream straight back to the webserver. It's not the best solution as for the time the file is sent, PHP still runs. For better results you'll need something like X-SendFile, which is supported on most webservers (if you install the correct modules).

In general (if you care about heavy load), it's best to put a proxying webserver in front of your main application server. This will free up your application server (for instance apache) up quicker, and proxy servers (Varnish, Squid) tend to be much better at transfering bytes to clients with high latency or clients that are generally slow.

Evert
  • 93,428
  • 18
  • 118
  • 189
2

If the file is publicly accessable, just do a simple redirect to the URL of your file.

Community
  • 1
  • 1
DarkDust
  • 90,870
  • 19
  • 190
  • 224
  • 8
    I can't vote down; but I would. The question is; how to make a file available accessing a php script. I guess we know that we can access a file directly, but using a php script as middle man gives as the control. I for example, want to allow some downloads to certain users, and the files could even be on a database. – Mike Sep 12 '14 at 17:49
  • 5
    I would downvote your comment if I could! :) The OP is using PHP and wants the browser to download a file. You can create redirects with PHP - somthing that maybe that hadn't occured to the OP. DarkDust's answer fits the bill and is valid. – ban-geoengineering Nov 07 '14 at 22:31
  • 2
    I upvoted both of you because you both made valid points. – Andrew Dec 04 '21 at 15:29
1

If the file is public, then you can just serve it as a static file directly from the web server (e.g. Apache), and make download.php redirect to the static URL. Otherwise, you have to use readfile to send the file to the browser after authenticating the user (remember about the Content-Dispositon header).

Adam Byrtek
  • 12,011
  • 2
  • 32
  • 32