使用LuaSocket的HTTP模块下载大文件,同时保持UI响应

时间:2014-06-24 12:38:55

标签: http lua luasocket

我想使用LuaSocket的HTTP模块下载大文件,同时在控制台中显示进度,稍后在GUI中显示。 UI必须永远不会阻止,即使服务器在传输过程中没有响应也不会阻止。此外,创建工作线程来处理下载不是一种选择。

这是我到目前为止所得到的:

local io = io

local ltn12 = require("ltn12")
local http = require("socket.http")

local fileurl = "http://www.example.com/big_file.zip"
local fileout_path = "big_file.zip"

local file_size = 0
local file_down = 0

-- counter filter used in ltn12
function counter(chunk)
    if chunk == nil then
        return nil
    elseif chunk == "" then
        return ""
    else
        file_down = file_down + #chunk
        ui_update(file_size, file_down) -- update ui, run main ui loop etc.
        return chunk -- return unmodified chunk
    end
end

-- first request
-- determine file size
local r, c, h = http.request {
    method = "HEAD",
    url = fileurl
}
file_size = h["content-length"]

-- second request
-- download file
r, c, h = http.request {
    method = "GET",
    url = fileurl,
    -- set our chain, count first then write to file
    sink = ltn12.sink.chain(
        counter,
        ltn12.sink.file(io.open(fileout_path, "w"))
    )
}

上面有一些问题,忽略了错误检查和硬编码:

  1. 当只有1(普通GET请求也发送内容长度)时,它需要2个HTTP请求
  2. 如果服务器没有响应,则UI也将无响应,因为只有在有数据需要处理时才会调用过滤器。
  3. 我怎样才能确保UI永远不会阻止?

1 个答案:

答案 0 :(得分:1)

non-preemptive multithreading in Programming in Lua上有一个使用非阻塞luasocket调用和协同程序进行多个并行下载的示例。应该可以将相同的逻辑应用于您的进程以避免阻塞。我只能补充一点,你应该考虑从你的GUI中的IDLE事件调用这个逻辑(如果有这样的事情),以避免“尝试跨越元方法/ c调用边界”错误。