通常后端程序响应文件下载请求时,可以通过设定响应头和文件类型,读取文件内容加载到内容,然后在响应内容中输出文件流的方式实现。例如python

self.set_header("Content-Type", 'application/dat; charset="utf-8"')
self.set_header("Content-Disposition", "attachment; filename=%s" % filename)
self.set_status(200)
with open(File, 'r') as f:
    content = f.read()
self.write(content)
return

这样的实现方式存在几个问题: 1. 在文件较大或者并发请求数较多的时候,程序将要占用大量的内存来存放文件内容 2. 难以实现断点续传 3. 进程将被挂起,等待传输完毕。文件越大,等待时间越长,执行效率越低

此时可以利用send-file机制,通过设定响应头将请求转发给代理服务器。应用程序不需要关心文件传输详情,而由更擅长处理静态文件传输的服务器来执行。

假设日志文件为/data/download/log/tornado.log 在tornado中,可以使用如下代码

filename = '/log/tornado.log'
self.set_header("Content-Type", "application/octet-stream")
self.set_header('X-Accel-Redirect',filename)
self.set_header("X-Accel-Buffering", "yes")

self.finish()

然后在nginx服务器配置加入

location /log/ {
    alias /data/download/log/;
    internal;
}

或者

location /log/ {
    root /data/download;
    internal;
}

与其他静态文件传输一样,可以借助其他nginx插件实现断点续传等功能