-- 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