9 votes

XSendFile ne sert pas les fichiers dans Apache 2.2

J'utilise mod_xsendfile (v0.12) pour servir des fichiers statiques où Django contrôle l'accès aux fichiers en fonction des utilisateurs et des autorisations.

Dans mon fichier conf, j'ai :

XSendFile On
XSendFilePath e:/documents/

<Directory e:/Documents>
  Order allow,deny
  Allow from all
</Directory>

Dans mon code django, je configure les en-têtes comme suit :

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

Et dans mon fichier journal, j'obtiens :

[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

Dans cette version de mod_xsendfile ,

XSendFileAllowAbove On

génère l'erreur :

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

J'ai supposé que c'était parce qu'ils ont ajouté le XSendFilePath liste blanche. Quelqu'un d'autre a réussi à faire fonctionner cela ?

13voto

nmaier Points 14425

Ne définissez pas vous-même une longueur de contenu. Cela ne fera qu'embrouiller les gestionnaires tels que mod_wsgi dans ce cas. Le mod_xsendfile définira lui-même la longueur de contenu correcte.

Sous Windows, vous devez non seulement fournir la lettre du lecteur, mais celle-ci doit être en majuscules (IIRC) !

J'ai une configuration de test qui fonctionne comme suit :

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

Un de mes scripts de test fonctionnel dans E:/Apache2.2/htdocs/ ressemble à ceci :

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

XSendFileAllowAbove a été supprimé il y a quelque temps en faveur de XSendFilePath.

3voto

Fabien Snauwaert Points 407

J'ai eu beaucoup de problèmes la plupart du temps lorsque j'ai dû configurer le chemin d'accès à XSendfile.

J'ai testé plusieurs scénarios sur Windows pour voir ce qui n'allait pas (allez à la fin de ce billet pour voir la conclusion et les recommandations) :

<?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();

?>

Donc, en gros, pour X-Sendfile sous Windows, assurez-vous que :

  • Vous utilisez des barres obliques dans votre configuration Apache pour XSendfilePath (obligatoire) ;
  • Respectez le cas dans vos parcours, même si nous sommes sous Windows (obligatoire) ;
  • Utiliser les chemins absolus partout (recommandé)
  • Pas de slashs de fin pour XSendfilePath (recommandé)

J'espère que cela aidera quelqu'un ! Fabien

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X