Skip to content

lua tcp socket read timed out #35

@bryant24

Description

@bryant24

hi,I use lua-resty-upload to handle big file upload, I use an extension of this version which have the part-split upload function, repos link, when the last part upload complete, the nginx error log sometimes show this error:
lua tcp socket read timed out
and did not merge all the part to one file,please give me a help!thx!
this is upload.lua script below:

local upload = require "resty.upload"
local cjson = require "cjson"
local get = ngx.req.get_uri_args()
local chunk_size = 4096
local file_upload_count = 0
local speed = 0
local post = {}
local index
local file
local upload_path = "/tmp/" -- 上传路径

--merge chunks
local function mergeChunks(chunks, name)
    local file = io.open(upload_path .. name, "w+")
    for i = 0, chunks - 1 do
        local chunk_path = upload_path .. name .. "." .. i
        local chunk_file = io.open(chunk_path)
        while true do
            local bytes = chunk_file:read(4096)
            if not bytes then
                break
            end
            file:write(bytes) 
        end
        chunk_file:close()
        os.remove(chunk_path)
    end
    file:close()
end

-- rate limit
if get.speed then
    speed = math.ceil(get.speed * 1024 / chunk_size)
end

local form, err = upload:new(chunk_size)
if not form then
    ngx.say("no zuo no die.")
    ngx.exit(200)
end

form:set_timeout(1000) -- one second timeout

while true do
    local typ, res, err = form:read()
    if not typ then
        ngx.say("failed to read: ", err)
        return
    end

    if typ == "header" then
        if res[1] == "Content-Disposition" then
            local filename = ngx.re.match(res[2], '(.+)filename="(.+)"(.*)')

            if filename then
                filename = filename[2]

                -- part upload
                if post["chunks"] then
                    filename = filename .. "." .. post["chunk"]
                end

                file = io.open(upload_path .. filename, "w+")
                if not file then
                    ngx.say("failed to open file ")
                    return
                end
            else
                local name = ngx.re.match(res[2], '(.+)name="(.+)"(.*)')
                if name[2] then
                    index = name[2]
                end    
            end
        end
    elseif typ == "body" then
        if file then
            -- record upload times
            file_upload_count = file_upload_count + 1

            -- rate limit
            if speed ~= 0 and file_upload_count % speed == 0 then
                ngx.sleep(1)
            end

            -- write file
            file:write(res)
        else
            if index then
                if post[index] == nil then
                    post[index] = res
                else
                    post[index] = post[index] .. res
                end
            end
        end
    elseif typ == "part_end" then
        if file then
            file:close()
            file = nil

            if post["chunks"] and post["chunk"] then
                if tonumber(post["chunks"]) - tonumber(post["chunk"]) == 1 then
                    mergeChunks(tonumber(post["chunks"]), post["name"])
                end
            end

            ngx.header["Content-Type"] = 'application/json'
            ngx.say(cjson.encode({code=1}))
        end
        if index then
            index = nil
        end
    elseif typ == "eof" then
        break
    else

    end

end

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions