OpenResty文件上传,支持java和前端上传
安装OpenResty
lua脚本,包括创建路径,再数据上传,并返回相对路径如下:
-- upload.lua
--==========================================
-- 文件上传
--==========================================
local upload = require "resty.upload"
local cjson = require "cjson"
local chunk_size = 4096
local form, err = upload:new(chunk_size)
if not form then
ngx.log(ngx.ERR, "failed to new upload: ", err)
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
form:set_timeout(1000)
-- 字符串 split 分割
string.split = function(s, p)
local rt= {}
string.gsub(s, '[^'..p..']+', function(w) table.insert(rt, w) end )
return rt
end
-- 支持字符串前后 trim
string.trim = function(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
-- 文件保存的根路径
local saveRootPath = ngx.var.store_dir
-- relname是相对路径文件名,创建不存在路径
function file_exists(relname)
local path = saveRootPath .. relname
-- local abspath=string.match(path, "(.+)/[^/]*%.%w+$")
local abspath
if string.match(path, "(.+)/[^/]*%.%w+$") ~= nil then
abspath=string.match(path, "(.+)/[^/]*%.%w+$")
else
abspath= path
end
testfile,errs = io.open(abspath,"rb")
if not testfile then
ngx.log(ngx.ERR,errs)
local md="mkdir -p "
local mdpath=md .. abspath
ngx.log(ngx.ERR,"not exist! start mkdir "..abspath)
os.execute(mdpath)
else
testfile:close()
end
end
-- 保存的文件对象
local fileToSave
--文件是否成功保存
local ret_save = false
local ret_str
local ret_key
local filepathname
while true do
local typ, res, err = form:read()
local ret_name_flag=true
if not typ then
ngx.say("failed to read: ", err)
return
end
if typ == "header" then
-- 开始读取 http header
-- 解析出本次上传的文件名
local key = res[1]
local value = res[2]
-- ret_key=value
if key == "Content-Disposition" then
-- 解析出本次上传的文件名
-- form-data; name="testFileName"; filename="testfile.txt"
-- form-data; name=
local kvlist = string.split(value, ';')
for _, kv in ipairs(kvlist) do
local seg = string.trim(kv)
if seg:find("name") == 1 then
local kvfile2 = string.split(seg, "=")
local filename = string.sub(kvfile2[2], 2, -2)
if string.match(filename, "(.+)/[^/]*%.%w+$") ~= nil then
file_exists(filename) -- 判断子文件夹是否存在,不存在创建
filepathname = filename
ret_key=filepathname
elseif filename:match("(.+)/[^/]*/$") ~= nil then
file_exists(filename) -- 判断子文件夹是否存在,不存在创建
filepathname = filename
ret_key=filepathname
elseif filename:match("(.+)/[^/]*%w+$") ~= nil then
file_exists(filename .. "/") -- 判断子文件夹是否存在,不存在创建
filepathname = filename .. "/"
ret_key=filepathname .. "/"
else
ngx.log(ngx.INFO, "get file path!!")
end
end
if seg:find("filename") then
local kvfile = string.split(seg, "=")
local filename
if filepathname ~= nil then
if string.match(filepathname, "(.+)/[^/]*%.%w+$") then
filename = filepathname
else
filename = filepathname .. string.sub(kvfile[2], 2, -2)
filepathname = filename
end
else
filename=string.sub(kvfile[2], 2, -2)
filepathname = filename
end
-- ret_key=filepathname
file_exists(filename) -- 判断子文件夹是否存在,不存在创建
if filename then
fileToSave = io.open(saveRootPath .. filename, "w+")
if not fileToSave then
ngx.say("failed to open file ", filename)
return
end
break
end
end
end
end
elseif typ == "body" then
-- 开始读取 http body
if fileToSave then
fileToSave:write(res)
end
elseif typ == "part_end" then
-- 文件写结束,关闭文件
if fileToSave then
fileToSave:close()
fileToSave = nil
end
ret_save = true
elseif typ == "eof" then
-- 文件读取结束
break
else
ngx.log(ngx.INFO, "do other things")
end
end
if ret_save then
ngx.say("",filepathname)
end
测试用例: