0

Is there any way to provide a direct link to a file and force the browser to download it using PHP?

E.g http://www.website.com/directory/file.jpg

We're dealing with huge files here and Chrome in particular seems to have a problem rendering the image, so all the user sees is a blank screen when visiting the file directly. Even though they can still right-click in the blank screen and download the file it's confusing.

We used to output the files from PHP but we ran into memory problems so switched to providing a direct link instead. The files go up to about 5GB, they aren't all images. We have zips, PDFs, PSDs etc.

Currently, the file is requested through a PHP script which accepts the ID of the file and get its URL. The PHP script then redirects to the user to full URL of the file.

How can we ensure that downloads are forced and we don't run into memory issues with the larger files?

Thank you

jd182
  • 3,180
  • 6
  • 21
  • 30
  • 2
    Perhaps [this answer](http://stackoverflow.com/questions/10596116/caching-http-responses-when-they-are-dynamically-created-by-php/10596231#10596231) will help you. – Ja͢ck Jul 09 '13 at 09:26
  • This seems to be a web server configuration issue though; just add a `Content-Type: application/octet-stream` to all files in a particular directory. – Ja͢ck Jul 09 '13 at 09:32

3 Answers3

3

Just use X-Sendfile but you need to configure it first ... using XSendFilePath

if (file_exists($file)) {
    header("X-Sendfile: $file");
    header("Content-Type: application/octet-stream");
    header(sprintf("Content-Disposition: attachment; filename=\"%s\"", basename($file)));
    exit();
}

Note* Please ensure $file is properly escaped before you verify and serve the file

XSendFilePath only works on Apache for other servers please see : Caching HTTP responses when they are dynamically created by PHP

Community
  • 1
  • 1
Baba
  • 94,024
  • 28
  • 166
  • 217
0

You need to set the headers for force download

        $file = 'upload_directory_path/'.$image_name;

        if (file_exists($file)) {
            header('Content-Description: File Transfer');
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment; filename='.basename($file));
            header('Content-Transfer-Encoding: binary');
            header('Expires: 0');
            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
            header('Pragma: public');
            header('Content-Length: ' . filesize($file));
            ob_clean();
            flush();
            readfile($file);
            exit;
        }
Khawer Zeshan
  • 9,470
  • 6
  • 40
  • 63
0
<?php 
//file path
$file = 'monkey.gif';

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit;
}
Sundar
  • 4,580
  • 6
  • 35
  • 61
  • This is similar to how we were doing it originally. The problem is when someone trys to download a 5GB file it eats the memory. Should this work for those large files? – jd182 Jul 09 '13 at 09:22
  • 1
    yes it'll work if your server has the proper configurations.. but 5 GB download just zip the file and call the URL simple – Sundar Jul 09 '13 at 09:24