代码之家  ›  专栏  ›  技术社区  ›  boatcoder

XSendFile不会提供Apache 2.2中的文件

  •  9
  • boatcoder  · 技术社区  · 15 年前

    我在用 mod_xsendfile (v0.12)提供静态文件,Django根据用户和权限控制对文件的访问。

    XSendFile On
    XSendFilePath e:/documents/
    
    <Directory e:/Documents>
      Order allow,deny
      Allow from all
    </Directory>
    

    在我的django代码中,我将标题设置为:

    assert(isinstance(filename, FieldFile))
    
    xsendfile = filename.name
    if(platform.system() == 'Windows'):
        xsendfile = xsendfile.replace('\\', '/')
    
    response = HttpResponse()
    response['X-Sendfile'] = xsendfile
    mimetype = mimetypes.guess_type(xsendfile)[0]
    response['Content-Type'] = mimetype
    response['Content-Length'] = filename.size
    

    在我的日志文件中我得到:

    [Fri Oct 22 08:54:22 2010] [error] [client 192.168.20.34] (20023)The given path
    was above the root path: xsendfile: unable to find file:
    e:/Documents/3/2010-10-20/TestDocument.pdf
    

    在这个版本的 mod_xsendfile ,

    XSendFileAllowAbove On
    

    生成错误:

    Invalid command 'XSendFileAllowAbove', perhaps misspelled or defined by a module
    not included in the server configuration
    

    XSendFilePath 白名单。还有人能用这个吗?

    2 回复  |  直到 12 年前
        1
  •  13
  •   nmaier    15 年前

    不要自己设置内容长度。在本例中,这只会使mod_wsgi之类的处理程序感到困惑。 mod xsendfile本身将设置正确的内容长度。

    在Windows上,您不仅必须提供驱动器号,而且驱动器号必须实际为大写(IIRC)!

    我的测试配置如下:

    <Directory "E:/">
      XSendFile on
      XSendFilePath E:/localhosts
    </Directory>
    

    我在E:/Apache2.2/htdocs/中的一个工作测试脚本如下所示:

    <?php
      header('X-SendFile: E:/localhosts/archive.tar.bz2');
      header('Content-type: application/octet-stream');
      header('Content-disposition: attachment; filename="blob"');
    ?>
    

        2
  •  2
  •   Fabien Snauwaert    12 年前

    大多数时候,我不得不配置XSendfile路径,这给我带来了很多麻烦。

    下面我将在Windows上测试几个场景,看看哪里出了问题(跳到本文末尾查看广告建议的结论):

    <?php
    
    /* X-SENDFILE
     * This can be a b*tch to configure. So I'm writing various scenarios here so that I can rely on them in the future.
     * Example use: after re-installing XAMPP, after changing config file, in a new script, after some time without using it...
     * Tested on Windows 7 + XAMPP (Apache/2.4.3, PHP/5.4.7) + mod_xsendfile 1.0-P1 for Apache 2.4.x Win32
     */
    
    /** Environment Debug **/
    //echo dirname(__FILE__);   die();
    //echo $_SERVER['DOCUMENT_ROOT'];   die();
    
    /** The damn fucking path, with comments **/
    
    // Local file in execution directory.
    // Tested with: *no* XSendFilePath inside of the Apache config
    // Result: works fine.
    //header("X-Sendfile: " . 'localfile.zip' );
    
    // Local file in execution directory + relative path
    // Tested with: *no* XSendFilePath inside of the Apache config
    // Result: works fine.
    //header("X-Sendfile: " . '../xsendfile/localfile.zip' );
    
    // Local file in execution directory + absolute pathS
    // Tested with: *no* XSendFilePath inside of the Apache config
    // Result: works fine and a lot of flexibility on the slash and letter drive format combinations *BUT* case-sensitive
    //header("X-Sendfile: " . 'D:\Dropbox\XAMPP\web\tests\Languages\Apache\xsendfile\localfile.zip' );  // works fine
    //header("X-Sendfile: " . '\Dropbox\XAMPP\web\tests\Languages\Apache\xsendfile\localfile.zip' );    // works fine
    //header("X-Sendfile: " . 'D:/Dropbox/XAMPP/web/tests/Languages/Apache/xsendfile/localfile.zip' );  // works fine
    //header("X-Sendfile: " . '/Dropbox/XAMPP/web/tests/Languages/Apache/xsendfile/localfile.zip' );    // works fine
    //header("X-Sendfile: " . '/dropbox/XAMPP/web/tests/Languages/Apache/xsendfile/localfile.zip' );    // FAILS (case-sensitive)
    
    // File in the XSendFilePath directory + Absolute path
    // Tested with: XSendFilePath D:\Dropbox\XAMPP\web -- Mind the backward slashes
    // Result: FAILS! error.log => [Wed Feb 20 19:08:02.617971 2013] [:error] [pid 15096:tid 1768] (20023)The given path was above the root path: [client ::1:56658] xsendfile: unable to find file: D:\\Dropbox\\XAMPP\\web\\xsfile.zip
    //header("X-Sendfile: " . 'D:\Dropbox\XAMPP\web\xsfile.zip' );
    
    // File in the XSendFilePath directory + Absolute path
    // Tested with: XSendFilePath D:/Dropbox/XAMPP/web <== mind the forward slashes this time
    // Result: WORKS! Conclusion: XSendFilePath needs use forward slashes on Windows AND we don't need any trailing slash in it.
    header("X-Sendfile: " . 'D:\Dropbox\XAMPP\web\xsfile.zip' );
    
    /** We might wanna test also:
     * - How does backward slashes in both XSendfilePath and the header combine?
     * - The use of subdirectories.
     * /
    
    /** The rest of the headers (until otherwise stated, nothing special) **/
    header("Content-Type: application/zip");
    header("Content-Disposition: attachment; filename=\"" . 'blah.zip' . "\"");
    header("Content-Transfer-Encoding: binary");
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: public");
    header("Content-Description: File Transfer");
    
    /** Tell the script to stop (so the file download may start) **/
    die();
    
    
    ?>
    

    因此,基本上,对于Windows上的X-Sendfile,请确保:

    • 即使我们在Windows上,也要尊重你的行为方式(强制性的);
    • 处处使用绝对路径(推荐)

    希望它能帮助别人! 法比安

    推荐文章