mod_xsendfile

最後更新: 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.

  1. /home/vhosts/datahunter.org/public_html/test.bin
  2. /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

 

Creative Commons license icon Creative Commons license icon