27

I'm looking to add a "Download this File" function below every video on one of my sites. I need to force the user to download the file, instead of just linking to it, since that begins playing a file in the browser sometimes. The problem is, the video files are stored on a separate server.

Any way I can force the download in PHP?

Lucky
  • 16,787
  • 19
  • 117
  • 151
  • possible duplicate of [Forcing to download a file using PHP](http://stackoverflow.com/questions/1465573/forcing-to-download-a-file-using-php) – bummi Aug 05 '13 at 14:49

7 Answers7

56

You could try something like this:

<?php

// Locate.
$file_name = 'file.avi';
$file_url = 'http://www.myremoteserver.com/' . $file_name;

// Configure.
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary"); 
header("Content-disposition: attachment; filename=\"".$file_name."\"");

// Actual download.
readfile($file_url);

// Finally, just to be sure that remaining script does not output anything.
exit;

I just tested it and it works for me.

Please note that for readfile to be able to read a remote url, you need to have your fopen_wrappers enabled.

Top-Master
  • 7,611
  • 5
  • 39
  • 71
Paolo Bergantino
  • 480,997
  • 81
  • 517
  • 436
  • Just remember to go: str_replace('"', '\\"', $file_name) Before putting it in the header – Chris KL Feb 10 '09 at 07:49
  • 7
    The flaw with this is that all the video would run through his server. If the video is on a separate server for bandwidth reasons, this solution will not be acceptable. – Zoredache Feb 10 '09 at 07:57
  • Point taken. From the sound of the question, though, I got the impression that he does not have access to this remote server, otherwise it would be a trivial problem. If that is the case, as far as I know this would be the only solution. – Paolo Bergantino Feb 10 '09 at 08:18
  • I do have access to the remote server. –  Feb 10 '09 at 17:32
  • This works for me but it does not tell you the file size and estimated time left, is there a header you need to specify to do this? Also, is it possible to use the filename of the file as it was meant to be, not to re-set it? – jmoz Apr 12 '10 at 21:20
  • I have same problem, and access to remote file server? How to initiate download form app server and serve file from remote, without using bandwith of an app server? – zidane Jun 28 '10 at 13:07
  • The user is still prompted to save the file. – Geoffrey Apr 08 '11 at 13:38
  • 1
    I think using readfile will consume both sites bandwidth. the main reason someone wants to do this is to save some bandwidth – pouya Sep 13 '12 at 01:25
  • I assume the same. @pouya. The server must download the file and then the user downloads the file from the server – Ben Apr 07 '14 at 14:38
  • 1
    @Ben If you have access to the server that has the file, you could simply `readfile` from it instead of remotely, eliminating the double bandwidth issue. – Paolo Bergantino Apr 07 '14 at 18:35
6

Tested download.php file is

function _Download($f_location, $f_name){
  $file = uniqid() . '.pdf';

  file_put_contents($file,file_get_contents($f_location));

  header('Content-Description: File Transfer');
  header('Content-Type: application/octet-stream');
  header('Content-Length: ' . filesize($file));
  header('Content-Disposition: attachment; filename=' . basename($f_name));

  readfile($file);
}

_Download($_GET['file'], "file.pdf");

and the link to download is

<a href="download.php?file=http://url/file.pdf"> Descargar </a>
Victor
  • 13,914
  • 19
  • 78
  • 147
4

Try this:

<?php
$FileName = '/var/ww/file.txt';
header('Content-disposition: attachment; filename="'.$FileName.'"');
readfile($FileName);

The key is the header(). You need to send the header along with the download and it will force the "Save File" dialog in the user's browser.

matpie
  • 17,033
  • 9
  • 61
  • 82
1
<?php

    $file_name = 'video.flv';
    $file_url = 'http://www.myserver.com/secretfilename.flv';
    header('Content-Type: application/octet-stream');
    header("Content-Transfer-Encoding: Binary"); 
    header("Content-disposition: attachment; filename=\"".$file_name."\""); 
    echo file_get_contents($file_url);
    die;

?>
warodri
  • 11
  • 3
0

I don't know this is the best way or not but I like that, short & simple.

If you want to download file when you visit URL, you can do like below

<a href="resume.pdf" download></a>
<script>document.querySelector('a').click();</script>
Nisharg Shah
  • 16,638
  • 10
  • 62
  • 73
0

index.php

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>download</title>
</head>

<body>
        <a href="download.php?file=ID_do_arquivo"> download </a>
</body>
</html>

.htaccess

Options -Indexes
Options +FollowSymlinks
deny from all

download.php

$file = "pdf/teste.pdf";
 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();
}
  • 1
    Although your code looks great and more than likely answers the question, please add an explanation of how it works so that people can understand why it works. – Unbranded Manchester Jun 19 '20 at 22:03
-1
<?php
$FileName = '/var/ww/file.txt';
header('Content-disposition: attachment; filename="'.$FileName.'"');
readfile($FileName);

using this code. is it possible to save the file name to what you want. for example you have url: http://remoteserver.com/file.mp3 instead of "file.mp3" can you use this script to download the file as "newname.mp3"