HTTP头文件下载 [英] HTTP Headers for File Downloads

查看:318
本文介绍了HTTP头文件下载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个PHP脚本来处理文件下载,确定正在请求哪个文件,并设置适当的HTTP标头来触发浏览器实际下载文件(而不是在浏览器中显示)。



我现在有一些问题,有些用户报告某些文件被错误地标识(所以无论扩展名是什么,浏览器会将其视为GIF图像)。我猜这是因为我没有在响应头中设置Content-type。这很可能是这样吗?如果是这样,是否有一个相当通用的类型,可以用于所有文件,而不是试图解释每一个可能的文件类型?



目前我只设置值Content-disposition:attachment; filename = arandomf.ile



更新:我遵循本指南来构建一个更健壮的过程档案下载( http:/ /w-shadow.com/blog/2007/08/12/how-to-force-file-download-with-php/ ),但脚本执行时间和浏览器的下载对话框出现。谁能识别造成这种情况的瓶颈?



这是我的实现:

  / ** 
*将指定的文件输出到浏览器。
*
* @param string $ filePath输出文件的路径
* @param string $ fileName文件的名称
* @param string $ mimeType的类型文件
* /
函数outputFile($ filePath,$ fileName,$ mimeType =''){
//设置
$ mimeTypes =数组(
'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 ='';

//确定MIME类型
if($ mimeType ==''){
$ fileExt = strtolower(substr(strrchr($ filePath,'。'),1) );

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

//禁用输出缓冲
@ob_end_clean();

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

//发送标题
header('Content-Type:'。$ mimeType);
header('Content-Disposition:attachment; filename ='。$ fileName。'');
header('Content-Transfer-Encoding:binary');
header('Accept-Ranges:bytes');

//发送头文件:阻止文件缓存
头('Cache-Control:private');
header('Pragma:private');
header('Expires:Mon,26 Jul 1997 05:00:00 GMT');

//多部分 - 下载和下载恢复支持
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;

//发送头
头('HTTP / 1.1 206部分内容');
header('Content-Length:'。$ newLength);
header('Content-Range:bytes'。$ range - $ rangeEnd / $ size);
}
else {
$ newLength = $ size;
header('Content-Length:'。$ size);
}

//输出文件
$ 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);
}
}
}


解决方案

根据 RFC 2046(多用途Internet邮件扩展)



实现的建议操作接收到一个

application / octet-stream实体是
只是提供将数据放在
a文件中


所以我会去那个。 p>

I've written a PHP script that handles file downloads, determining which file is being requested and setting the proper HTTP headers to trigger the browser to actually download the file (rather than displaying it in the browser).

I now have a problem where some users have reported certain files being identified incorrectly (so regardless of extension, the browser will consider it a GIF image). I'm guessing this is because I haven't set the "Content-type" in the response header. Is this most likely the case? If so, is there a fairly generic type that could be used for all files, rather than trying to account for every possible file type?

Currently I'm only setting the value "Content-disposition: attachment; filename=arandomf.ile"

Update: I followed this guide here to build a more robust process for file downloads (http://w-shadow.com/blog/2007/08/12/how-to-force-file-download-with-php/), but there is a significant delay between when the script is executed and when the browser's download dialog appears. Can anyone identify the bottleneck that is causing this?

Here's my implementation:

/**
 * 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);
        }
    }
}

解决方案

Acoording to RFC 2046 (Multipurpose Internet Mail Extensions):

The recommended action for an implementation that receives an
"application/octet-stream" entity is to simply offer to put the data in a file

So I'd go for that one.

这篇关于HTTP头文件下载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆