最近在了解Linux底层知识时,关注到了Zero-Copy技术,然后就了解到文件下载的性能问题,进而发现了这篇文章。
这其实是很早很早的技术。
虽然这篇文章说的只是apache,其实其他的WebServer也是有的,请读者自行学习。
最简单的做法
很多时候,我们要完成一个文件下载的功能,只需要创建一个目录,然后把文件放到目录里,剩下的让Apache来完成就可以了。
使用PHP提供文件下载
然而有时不得不使用PHP来处理,比如需要做权限认证或其他的检查什么的。这种情况,一般我们会这样写:
authenticate(); # 权限认证或其他的检查$file = determine_file(); if (!file_exists($file)) trigger_error("File '$file' doesn't exist.", E_USER_ERROR); header("Content-type: application/octet-stream");header('Content-Disposition: attachment; filename="' . basename($file) . '"');header("Content-Length: ". filesize($file));readfile($file);
请注意到这里的readfile,此函数在将内容发送到客户端之前需要先读取PHP再到Apache的输出缓存区最后才发送到用户,也就意味着PHP需要读取文件的内容,这其实是可以优化的。
如果希望last-modified能够生效,需要指定if-modified-since头信息,在请求文件时会校验修改时间以确定是否只需发送304状态码。
X-SendFile帮你解围
使用Apache的mod_xsendfile模块可以有效的提升发送文件的速度,其原理是减少用户态和内核态数据之间的COPY,可以参考这篇文章sendfile原理,当然,最核心的原理还是上面提到的Zero-Copy技术。
authenticate(); # 权限认证或其他的检查$file = determine_file(); header("X-Sendfile: $file");header("Content-type: application/octet-stream");header('Content-Disposition: attachment; filename="' . basename($file) . '"');
此技术从Lighttp中引用过来。Nginx也支持,只是header名字为X-Accel-Redirect。
本文翻译自 blog.jasny.net/articles/ho…
– By makediff