On Sun, Mar 11, 2012 at 9:02 AM, lhmwzy <
lh...@gmail.com> wrote:
> 现在有lua-resty-upload,可以用来上传文件,能实现流式的lua-resty-download吗?比如要下载的文件不WEB目录中,用lua-resty-download去读,然后通过流式分段输出到客户端,以此来实现下载,适合于网盘等场合。
> 先问问能实现吗?
> 我水平低,想了想,没想出来如何分段输出。
> 分段读,然后输出到一个WEB临时文件,然后再让客户下载这个文件,下载完后,删除临时文件,这个思路对?
如果你的数据源是磁盘文件,可以使用类似下面的代码来分块读取文件内容并流式输出给下游 HTTP 连接:
local chunk_size = 4096 -- this is just an example
local file_path = "/tmp/big.txt" -- this is just an example
local f, err = io.open(file_path, "r")
if not f then
ngx.say("failed to open file: ", err)
return
end
while true do
local chunk = f:read(chunk_size)
if not chunk then
break
end
ngx.print(chunk)
ngx.flush(true)
end
这个例子中的关键是利用了 ngx.flush 这个接口:
http://wiki.nginx.org/HttpLuaModule#ngx.flush不过这里需要注意的一个问题是 ngx_lua 对于 HTTP 1.0 是自动对响应体进行全缓存的(为了支持 HTTP 1.0 Keepalive),而目前没有提供配置方式禁止此行为,所以当客户端发起的是 HTTP 1.0 请求,上面的代码并不能实现流式输出。我这两天将实现一个 lua_http10_buffering 配置选项,上面的例子中只要在 nginx.conf 中加上
lua_http10_buffering off;
就不会再有 HTTP 1.0 全缓存输出的行为了。
如果你需要输出的数据源并不在本机文件系统中,而是某个 TCP 连接,则可以把上例中的分块文件读取操作替换为 cosocket receive 操作。不过,如果后端不够强大,根本受不了慢速 TCP 连接的话(例如许多关系数据库的连接),还是在输出之前先全缓存到本地文件系统的好。
Best regards,
-agentzh