Files
resty_functions/dev/file_upload/upload_image.lua
T
2021-08-27 09:30:15 +08:00

223 lines
7.1 KiB
Lua

-- Require lua modules
local upload = require "resty/upload"
local uuid = require "resty.jit-uuid"
local redis = require "resty.redis"
local cjson = require "cjson"
---------------------------------------------------------------------------------------
-- Functions : String split
string.split = function(s, p)
local rt= {}
string.gsub(s, '[^'..p..']+', function(w) table.insert(rt, w) end )
return rt
end
-- Functions : Get file trim
string.trim = function(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
end
---------------------------------------------------------------------------------------
-- Init
---- Upload init
local chunk_size = 5 -- should be set to 4096 or 8192
-- for real-world settings
local form, error = upload:new(chunk_size)
if not form then
ngx.log(ngx.ERR, "Fail to create new form: ", error)
ngx.exit(500)
end
---- Automatic seeding with os.time(), LuaSocket, or ngx.time()
uuid.seed()
uuid()
---- Redis init
------ Connect to redis
local redis_task_database = redis:new()
redis_task_database:set_timeouts(1000, 1000, 1000)
local ok, error = redis_task_database:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "Fail to connect redis: ", error)
ngx.exit(500)
end
---------------------------------------------------------------------------------------
-- Save upload images
---- Upload file save path config in nginx.conf
local save_upload_file_path = ngx.var.store_dir
local file_to_save
local ret_save = false
local upload_image_filename
local save_image_filename
local upload_image_table = {}
local data_table = {}
local upload_image_index = 1
form:set_timeout(1000) -- 1 sec
---- Read image file from http packet and save it
while true do
local http_type, result, error = form:read()
if not http_type then
ngx.log(ngx.ERR, "Failed to read form: ", error)
ngx.exit(500)
end
if http_type == "header" then
-- Start to read http header
local key = result[1]
local value = result[2]
if key == "Content-Disposition" then
-- Analyze this time upload image filename , use ; as interval
-- Like: form-data; name="testFileName"; filename="testfile.txt"
local key_value_list = string.split(value, ';')
for _, key_value in ipairs(key_value_list) do
local segment = string.trim(key_value)
if segment:find("filename") then
local key_value_file = string.split(segment, "=")
upload_image_filename = string.sub(key_value_file[2], 2, -2)
ngx.log(ngx.INFO, "Upload origin filename: ", upload_image_filename)
-- Save upload file
if upload_image_filename then
-- Save file name with generate uuid
save_image_filename = uuid:generate_v4() -- Generate save filename uuid
save_image_filename = save_image_filename .. '.' .. upload_image_filename:match(".+%.(%w+)$")
file_to_save = io.open(save_upload_file_path .. save_image_filename, "w+")
if not file_to_save then
ngx.log(ngx.ERR , "Fail open file: ", save_image_filename)
ngx.exit(500)
else
ngx.log(ngx.INFO, "Success open file: ", save_image_filename)
-- Save all upload files as a table
data_table[upload_image_index] = save_image_filename
upload_image_table[upload_image_index] = save_upload_file_path .. save_image_filename .. " "
ngx.log(ngx.INFO, "Insert upload image table "..upload_image_index.." with "..upload_image_table[upload_image_index])
upload_image_index = upload_image_index + 1
end
break
end
end
end
end
elseif http_type == "body" then
-- Start to read http body
if file_to_save then
file_to_save:write(result)
end
elseif http_type == "part_end" then
-- Write to save file finish
if file_to_save then
file_to_save:close()
file_to_save = nil
end
ret_save = true
elseif http_type == "eof" then
-- Read file end
break
else
ngx.log(ngx.INFO, "Maybe do other things")
end
end
---------------------------------------------------------------------------------------
-- Show all input and may output files
if ret_save then
ngx.log(ngx.INFO, "Show all upload save files\n")
---- Show all upload save files
upload_image_index = upload_image_index -1
for i = 1, upload_image_index do
ngx.log(ngx.INFO, "Save upload file is : " .. upload_image_table[i])
end
---------------------------------------------------------------------------------------
-- Communicate with front end
---- Generate task uuid
local task_uuid = uuid.generate_v4();
---------------------------------------------------------------------------------------
-- Construct {key: task_id | value: [images] } in json
-- Example:
-- {"task_id":"488a8e6c556a-4271-adec--071e843c9856","data:"[\"2109aac0-556a-4271-adec-9eac494f622f.jpg\",\"488a8e6c-01e6-4cb3-af88-a1d90e04e6b8.jpg\",\"c3f76317-592f-4117-ab0d-071e843c9856.jpg\"]"}
local task_table = {}
task_table["task_id"] = task_uuid
task_table["data"] = data_table
local task_jason = cjson.encode(task_table)
ngx.log(ngx.INFO , task_jason) -- Response to front end
---------------------------------------------------------------------------------------
-- Redis control
---- Set json to redis
ok, error = redis_task_database:set(task_uuid, task_jason)
if not ok then
ngx.log(ngx.ERR , "Failed to set task json: ", error)
ngx.exit(500)
end
ngx.log(ngx.INFO , "Set redis task json result: ", ok)
---- Get data from redis
local result, error = redis_task_database:get(task_uuid)
if not result then
ngx.log(ngx.ERR , "Failed to get task json: ", error)
ngx.exit(500)
end
if result == ngx.null then
ngx.log(ngx.ERR , "Not found task id")
ngx.exit(500)
end
ngx.log(ngx.INFO, "Get redis task id: " .. task_uuid .. " | value :" .. result)
---------------------------------------------------------------------------------------
-- Create task
local result = ngx.location.capture(
'/mock_task_server',
{
method = ngx.HTTP_POST,
body = ngx.encode_args({task = task_jason})
}
)
ngx.say(result.body)
-- Response task ID to front end
ngx.say(task_uuid)
-- Mock a image append request from task from task server
local result = ngx.location.capture(
'/image_append',
{
method = ngx.HTTP_POST,
body = ngx.encode_args({task = task_jason})
}
)
ngx.say(result.body)
end