php文件下载的一些浅谈

来源:互联网 发布:南阳网络推广哪家专业 编辑:程序博客网 时间:2024/06/05 11:36

在web开发过程中,文件的上传下载是必须的,同时竟会经常出现一些无厘头的bug,接下来讲一些php文件下载需要注意的地方。

(1)php解释器配置文件是必不可少的,在php.ini配置文件中 开启phpinfo.dll扩展

extension=php_fileinfo.dll 去掉前面的;即可

(2)如果经验丰富的话,我们知道,一些简单的文件下载,如docx,rar等一些文件格式的,由于它是不能被浏览器默认识别的MIME类型,因为在实现下载时只需要用<a href="....../docx/xxx.docx"></a>链接地址指向文件存储路径即可,浏览器会自动弹出打开或下载的提示框,这样客户端便可以实现下载,但是对于图片格式,如gif、jpg

还有视频格式,如MP4、wmv等文件格式的,当我们还是使用上面那种方式时,发现浏览器会直接打开它,并不会提示下载,这是因为这些文件类型是浏览器可是默认识别的。

这时,我们就需要通过另一种方式来实现了。

上述通过<a>实现的下载实际上是不安全的,因为将文件路径信息暴露在了浏览器中。合适的做法应该是服务器端通过header将头信息回传给浏览器,该函数接受一个头信息作为参数。文件下载需要发送的头信息包括以下三部分,通过调用三次header()函数完成

header(‘Content-Type:imge/gif'); //发送指定文件MIME类型的头信息header(‘Content-Disposition:attachment; filename=”test.gif”‘); //发送描述文件的头信息,附件和文件名header(‘Content-Length:3390′); //发送指定文件大小的信息,单位字节

有了这三个头信息,浏览器就不会直接打开文件,而是让浏览器以下载形式打开文件。接下来就需要将文件内容输出到浏览器,以便浏览器进行下载,使用php中的readfile()函数,可以文件直接输出。

(3)下面讲一下tp框架中的Http.class.php中的download方法(个人感觉还是很好用的!)

 public static function download($filename, $showname = '', $content = '', $expire = 180)    {        ob_end_clean();        if (is_file($filename)) {            $length = filesize($filename);        } elseif (is_file(UPLOAD_PATH . $filename)) {            $filename = UPLOAD_PATH . $filename;            $length   = filesize($filename);        } elseif ('' != $content) {            $length = strlen($content);        } else {            E($filename . L('下载文件不存在!'));        }        if (empty($showname)) {            $showname = $filename;        }        $showname = basename($showname);        if (!empty($filename)) {            $finfo = new \finfo(FILEINFO_MIME);            $type  = $finfo->file($filename);        } else {            $type = "application/octet-stream";        }        //发送Http Header信息 开始下载        header("Pragma: public");        header("Cache-control: max-age=" . $expire);        //header('Cache-Control: no-store, no-cache, must-revalidate');        header("Expires: " . gmdate("D, d M Y H:i:s", time() + $expire) . "GMT");        header("Last-Modified: " . gmdate("D, d M Y H:i:s", time()) . "GMT");        header("Content-Disposition: attachment; filename=" . $showname);        header("Content-Length: " . $length);        header("Content-type: " . $type);        header('Content-Encoding: none');        header("Content-Transfer-Encoding: binary");        if ('' == $content) {            readfile($filename);        } else {            echo ($content);        }        exit();    }

前面的获取文件内容,设置下载附件名字,获取文件大小、类型在这里不做过多介绍,这些大家都能看懂,主要说一下下面的几个header()函数。

header("Pragma: public");  

pragma是HTTP 1.0协议,通常在不缓存情况下使用,通常为 pragma:no-cache  这儿设置public 应该是可以在任何地方缓存

header("Cache-control: max-age=" . $expire);  


上述是Cache-control可以设定的一些参数值,这里设置的是 max-age:内容能被缓存的时间,这个参数由调用时方法参数给定。

header("Last-Modified: " . gmdate("D, d M Y H:i:s", time()) . "GMT");  

客户端通过浏览器访问服务器第一次请求时,服务器端的返回状态是200,内容是客户端请求资源,同时还会有一个Last-Modified的属性标记此文件在服务期端最后被修改的时

间,当浏览器第二次访问服务器的时候,浏览器会发送一个If-Modified-Since 报头,询问该时间之后文件是否有被修改过,如果没有修改的话,服务器会返回一个304状态吗,

内容为空,这样就可以节省数据流量。

header("Expires: " . gmdate("D, d M Y H:i:s", time() + $expire) . "GMT");  

设定浏览器缓存时间,在浏览器中有缓存区。这时当浏览器向同一url发送请求时,浏览器有两种处理方式:

1.直接在缓冲区内取资源:如果在服务器端设置了expires,max-age时,浏览器不会在有效时期内再去向服务器发送请求,而是直接从缓存区取资源

2.向浏览器发送请求资源。这种情况发生在在头部设置expires:no-cache时,或者是设置了 Expires,max-age但浏览器行为是 ' 刷新' 或 '重载'时候。

header('Content-Encoding: none');  header("Content-Transfer-Encoding: binary");

http协议中的编码协议和数据传输编码协议,第一个none表示编码内容默认,通常它有gzip,deflate,compress三种方式。第二个表示使用二进制方式传输。

下面说一个使用http.class.php中的download方法过程中需要注意的:

(1)下载文件名最好不要用中文命名,经常会出现找不到下载文件的问题。

(2)如果下载完成后,例如下载了一个视频文件,但是打开时显示无效文件。这时下载过程中的错误,这时候尝试在执行下载操作前,清空浏览器缓存区。使用ob_end_clean()函数。这个问题在使用tp框架中的verify时,验证码图片加载不出来也同样适用。

(3)Http:download($filename,$showname); 中的第二个参数一定要标识文件后缀名,第一个参数为文件所在路径。


0 0