最後更新: 2017-10-31
介紹
Apache2 module that processes X-SENDFILE headers registered by the original output handler.
If it encounters the presence of such header it will discard all output and send the file specified by that header
instead using Apache internals including all optimizations like caching-headers and sendfile or mmap if configured.
Homepage:
https://tn123.org/mod_xsendfile/
Apache - Sendfile
# Use the kernel sendfile support to deliver files to the client
EnableSendfile On
# When delivering a static file
# Apache httpd uses sendfile to deliver the file contents
# without ever reading the file if the OS supports it.
# This sendfile mechanism avoids separate read and send operations, and buffer allocations.
With a network-mounted DocumentRoot (e.g., NFS, SMB, CIFS, FUSE),
the kernel may be unable to serve the network file through its own cache.
<Directory "/path-to-nfs-files"> EnableSendfile Off </Directory>
* It is useful for processing script-output of e.g. php, perl or any cgi.
(checking for special privileges)
mod_xsendfile
# Centos7 Install
yum install mod_xsendfile
# Enables header processing
XSendFile on
# All files within these paths are allowed to get served through mod_xsendfile
# may provide more than one path
# 此 Path 會 Inheritance, 有疊加效果
XSendFilePath /home/tim/web/private_data
* The Content-Encoding header - if present - will be dropped (不能 compression)
* The header key (X-SENDFILE) is not case-sensitive.
* X-Sendfile will also send files that are otherwise protected
(e.g. Deny from all)
Relative paths
假設有 setting
XSendFilePath /home/tim/web/private_data
test.php
header("X-Sendfile: test.bin");
/home/vhosts/datahunter.org/public_html/test.php
# The current working directory (if it can be determined) will be always checked first.
- /home/vhosts/datahunter.org/public_html/test.bin
- /home/vhosts/datahunter.org/private_data/test.bin
測試
wget --limit-rate=10m http://192.168.88.210/test.php; rm -f test.php
wget --limit-rate=10m http://192.168.88.210/test.bin; rm -f test.bin
Other Setting
"Expires: 0"
means that a cache will always treat this entry as stale (i.e. it will need to revalidate it first before returning it to a client).
Pragma: public'
# Indicates that the response MAY be cached by any cache,
# even if it would normally be non-cacheable or cacheable only within a non-shared cache.
# It is used in Google App Engine applications to enable caching of responses within its Edge Cache.
# public / private / nocache
php script
<?php $file="/home/vhosts/datahunter.org/private/file.pdf"; if (file_exists($file)) { //header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); //header('Pragma: no-cache'); header("Content-Type: application/octet-stream"); header('Content-Length: ' . filesize($file)); header('Content-Disposition: attachment; filename="file.pdf"'); header("X-Sendfile: $file"); } else { die('File loading failed.'); } ?>
原先的 php scripts
* 會佔用 filesize 數量的 memory, 並且吃 CPU 資源
<?php $file = 'test.bin'; if (file_exists($file)) { header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.basename($file).'"'); header('Content-Length: ' . filesize($file)); header('Expires: 0'); header('Pragma: private'); readfile($file); exit; } ?>
wget content-disposition not working
# on a redirect the last component of the redirection URL will be used as the local file name
--trust-server-names
# This can currently result in extra round-trips to the server for a "HEAD" request
# use "Content-Disposition" headers to describe what the name of a downloaded file should be
--content-disposition