En-têtes HTTP pour les téléchargements de fichiers

J'ai écrit un script PHP qui gère les téléchargements de fichiers, en déterminant quel fichier est demandé et en définissant les en-têtes HTTP appropriés pour déclencher le navigateur pour télécharger le fichier (plutôt que de l'afficher dans le navigateur).

J'ai maintenant un problème où certains utilisateurs ont signalé que certains fichiers étaient mal identifiés (donc indépendamment de l'extension, le navigateur le considérera comme une image GIF). Je suppose que c'est parce que je n'ai pas défini le "Content-type" dans la réponse tête. Est-ce la plus probable? Si oui, est-il un générique type qui peut être utilisé pour tous les fichiers, plutôt que d'essayer de compte pour chaque type de fichier?

Actuellement, Je ne définis que la valeur "Content-disposition: attachment; filename=arandomf.ile "

Mise à jour: j'ai suivi ce guide ici pour construire un processus plus robuste pour les téléchargements de fichiers ( http://w-shadow.com/blog/2007/08/12/how-to-force-file-download-with-php/), mais il y a une délai entre le moment où le script est exécuté et le moment où la boîte de dialogue de téléchargement du navigateur apparaît. Quelqu'un peut-il identifier le goulot d'étranglement qui cause cela?

Voici mon implémentation:

/**
 * Outputs the specified file to the browser.
 *
 * @param string $filePath the path to the file to output
 * @param string $fileName the name of the file
 * @param string $mimeType the type of file
 */
function outputFile($filePath, $fileName, $mimeType = '') {
    // Setup
    $mimeTypes = array(
        'pdf' => 'application/pdf',
        'txt' => 'text/plain',
        'html' => 'text/html',
        'exe' => 'application/octet-stream',
        'zip' => 'application/zip',
        'doc' => 'application/msword',
        'xls' => 'application/vnd.ms-excel',
        'ppt' => 'application/vnd.ms-powerpoint',
        'gif' => 'image/gif',
        'png' => 'image/png',
        'jpeg' => 'image/jpg',
        'jpg' => 'image/jpg',
        'php' => 'text/plain'
    );

    $fileSize = filesize($filePath);
    $fileName = rawurldecode($fileName);
    $fileExt = '';

    // Determine MIME Type
    if($mimeType == '') {
        $fileExt = strtolower(substr(strrchr($filePath, '.'), 1));

        if(array_key_exists($fileExt, $mimeTypes)) {
            $mimeType = $mimeTypes[$fileExt];
        }
        else {
            $mimeType = 'application/force-download';
        }
    }

    // Disable Output Buffering
    @ob_end_clean();

    // IE Required
    if(ini_get('zlib.output_compression')) {
        ini_set('zlib.output_compression', 'Off');
    }

    // Send Headers
    header('Content-Type: ' . $mimeType);
    header('Content-Disposition: attachment; filename="' . $fileName . '"');
    header('Content-Transfer-Encoding: binary');
    header('Accept-Ranges: bytes');

    // Send Headers: Prevent Caching of File
    header('Cache-Control: private');
    header('Pragma: private');
    header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');

    // Multipart-Download and Download Resuming Support
    if(isset($_SERVER['HTTP_RANGE'])) {
        list($a, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2);
        list($range) = explode(',', $range, 2);
        list($range, $rangeEnd) = explode('-', $range);

        $range = intval($range);

        if(!$rangeEnd) {
            $rangeEnd = $fileSize - 1;
        }
        else {
            $rangeEnd = intval($rangeEnd);
        }

        $newLength = $rangeEnd - $range + 1;

        // Send Headers
        header('HTTP/1.1 206 Partial Content');
        header('Content-Length: ' . $newLength);
        header('Content-Range: bytes ' . $range - $rangeEnd / $size);
    }
    else {
        $newLength = $size;
        header('Content-Length: ' . $size);
    }

    // Output File
    $chunkSize = 1 * (1024*1024);
    $bytesSend = 0;

    if($file = fopen($filePath, 'r')) {
        if(isset($_SERVER['HTTP_RANGE'])) {
            fseek($file, $range);

            while(!feof($file) && !connection_aborted() && $bytesSend < $newLength) {
                $buffer = fread($file, $chunkSize);
                echo $buffer;
                flush();
                $bytesSend += strlen($buffer);
            }

            fclose($file);
        }
    }
}
41
demandé sur animuson 2008-12-22 20:40:35

3 réponses

Selon RFC 2046 (Extensions de messagerie Internet polyvalentes):

L'action recommandée pour un implémentation qui reçoit un
l'entité "application / octet-stream" est pour offrir simplement de mettre les données dans un fichier

Donc j'irais pour celui-là.

35
répondu Greg 2008-12-22 17:45:49

Comme expliqué par le lien D'Alex, il vous manque probablement l'en-tête Content-Disposition au-dessus de Content-Type.

Donc quelque chose comme ceci:

Content-Disposition: attachment; filename=MyFileName.ext
39
répondu Simon East 2015-10-26 21:31:48

Vous pouvez essayer ce script Forcer le téléchargement . Même si vous ne l'utilisez pas, cela vous dirigera probablement dans la bonne direction:

<?php

$filename = $_GET['file'];

// required for IE, otherwise Content-disposition is ignored
if(ini_get('zlib.output_compression'))
  ini_set('zlib.output_compression', 'Off');

// addition by Jorg Weske
$file_extension = strtolower(substr(strrchr($filename,"."),1));

if( $filename == "" ) 
{
  echo "<html><title>eLouai's Download Script</title><body>ERROR: download file NOT SPECIFIED. USE force-download.php?file=filepath</body></html>";
  exit;
} elseif ( ! file_exists( $filename ) ) 
{
  echo "<html><title>eLouai's Download Script</title><body>ERROR: File not found. USE force-download.php?file=filepath</body></html>";
  exit;
};
switch( $file_extension )
{
  case "pdf": $ctype="application/pdf"; break;
  case "exe": $ctype="application/octet-stream"; break;
  case "zip": $ctype="application/zip"; break;
  case "doc": $ctype="application/msword"; break;
  case "xls": $ctype="application/vnd.ms-excel"; break;
  case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
  case "gif": $ctype="image/gif"; break;
  case "png": $ctype="image/png"; break;
  case "jpeg":
  case "jpg": $ctype="image/jpg"; break;
  default: $ctype="application/force-download";
}
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false); // required for certain browsers 
header("Content-Type: $ctype");
// change, added quotes to allow spaces in filenames, by Rajkumar Singh
header("Content-Disposition: attachment; filename=\"".basename($filename)."\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filename));
readfile("$filename");
exit();
6
répondu OIS 2013-10-08 09:00:38