local upload = require("resty.upload") local uuid = require("app.libs.uuid") local sfind = string.find local match = string.match local ngx_var = ngx.var local function getextension(filename) return filename:match(".+%.(%w+)$") end local function _multipart_formdata(config) local form, err = upload:new(config.chunk_size) if not form then ngx.log(ngx.ERR, "failed to new upload: ", err) ngx.exit(500) end form:set_timeout(config.recieve_timeout) local unique_name = uuid() local success, msg = false, "" local file, origin_filename, filename, path, extname, err while true do local typ, res, err = form:read() if not typ then success = false msg = "failed to read" ngx.log(ngx.ERR, "failed to read: ", err) return success, msg end if typ == "header" then if res[1] == "Content-Disposition" then key = match(res[2], "name=\"(.-)\"") origin_filename = match(res[2], "filename=\"(.-)\"") elseif res[1] == "Content-Type" then filetype = res[2] end if origin_filename and filetype then if not extname then extname = getextension(origin_filename) end if extname ~= "png" and extname ~= "jpg" and extname ~= "jpeg" and extname ~= "bmp" and extname ~= "gif" then success = false msg = "not allowed upload file type" ngx.log(ngx.ERR, "not allowed upload file type:", origin_filename) return success, msg end filename = unique_name .. "." .. extname path = config.dir.. "/" .. filename file, err = io.open(path, "w+") if err then success = false msg = "open file error" ngx.log(ngx.ERR, "open file error:", err) return success, msg end end elseif typ == "body" then if file then file:write(res) success = true else success = false msg = "upload file error" ngx.log(ngx.ERR, "upload file error, path:", path) return success, msg end elseif typ == "part_end" then file:close() file = nil elseif typ == "eof" then break else -- do nothing end end return success, msg, origin_filename, extname, path, filename end local function uploader(config) return function(req, res, next) if ngx_var.request_method == "POST" then local get_headers = ngx.req.get_headers() local header = get_headers['Content-Type'] if header then local is_multipart = sfind(header, "multipart") if is_multipart and is_multipart>0 then config = config or {} config.dir = config.dir or "/tmp" config.chunk_size = config.chunk_size or 4096 config.recieve_timeout = config.recieve_timeout or 20000 -- 20s local success, msg, origin_filename, extname, path, filename = _multipart_formdata(config) if success then req.file = req.file or {} req.file.success = true req.file.origin_filename = origin_filename req.file.extname = extname req.file.path = path req.file.filename = filename else req.file = req.file or {} req.file.success = false req.file.msg = msg end next() else next() end else next() end else next() end end end return uploader