📜 ⬆️ ⬇️

We give files efficiently using PHP

If you needed to give the files not directly to the web server, but using PHP (for example, to collect download statistics), please use the cat.

1. Use readfile()


The method is good because it works with the box. You just need to write your function to send the file (a slightly modified example from the official documentation ):

 function file_force_download($file) { if (file_exists($file)) { //    PHP,        //          ! if (ob_get_level()) { ob_end_clean(); } //       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)); //       readfile($file); exit; } } 

In this way, you can even send large files, since PHP will read the file and immediately give it to the user in parts. The documentation clearly states that readfile() should not create memory problems.

Features:

2. Read and send the file manually


The method uses the same Drupal when sending files from a private file system (files are not directly accessible by reference):
')
 function file_force_download($file) { if (file_exists($file)) { //    PHP,        //          ! if (ob_get_level()) { ob_end_clean(); } //       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)); //       if ($fd = fopen($file, 'rb')) { while (!feof($fd)) { print fread($fd, 1024); } fclose($fd); } exit; } } 

Features:

3. Using the web server module


3a. Apache

The XSendFile module allows using a special header to transfer the file sending to Apache itself. There are versions on Unix and Windows, under version 2.0. *, 2.2. * And 2.4. *

In the host settings, you need to enable header interception using the directive:
 XSendFile On 

You can also specify a white list of directories in which files can be processed. Important: if you have a Windows-based server, the path must include the drive letter in upper case.

Description of possible options on the developer's site: https://tn123.org/mod_xsendfile/

Example of sending a file:

 function file_force_download($file) { if (file_exists($file)) { header('X-SendFile: ' . realpath($file)); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename=' . basename($file)); exit; } } 


3b. Nginx

Nginx can send files out of the box through a special header.

To work correctly, you need to deny access to the folder directly through the configuration file:
 location /protected/ { internal; root /some/path; } 

An example of sending a file (the file must be located in the / some / path / protected directory):

 function file_force_download($file) { if (file_exists($file)) { header('X-Accel-Redirect: ' . $file); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename=' . basename($file)); exit; } } 

More information on the official documentation page.

Features:


Update: Habrayuzer ilyaplot gives practical advice that it is better to send not the application/octet-stream , but the real mime type of the file. For example, this will allow the browser to substitute the necessary programs in the file saving dialog.

Source: https://habr.com/ru/post/151795/


All Articles