From a5b1a27141446cb80a5069c1f3f4925ecaa4e8c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=8B=87?= Date: Tue, 20 Jul 2021 21:44:28 +0800 Subject: [PATCH] . --- file_upload/nginx.conf | 99 +++++++++++++++ file_upload/upload_image.lua | 235 +++++++++++++++++++++++++++++++++++ 2 files changed, 334 insertions(+) create mode 100644 file_upload/nginx.conf create mode 100644 file_upload/upload_image.lua diff --git a/file_upload/nginx.conf b/file_upload/nginx.conf new file mode 100644 index 0000000..38ad470 --- /dev/null +++ b/file_upload/nginx.conf @@ -0,0 +1,99 @@ +worker_processes 1; +error_log logs/error.log info; +events { + worker_connections 1024; +} +http { + #Lua file path + #;; means openresty default path + lua_package_path "/Users/liyong/Code/Lua/lua-rest/openresty/conf/lua/?.lua;;"; + lua_package_cpath "/Users/liyong/Code/Lua/lua-rest/openresty/conf/c_ffi/add/?.so;;"; + + #Only use for debug +# lua_code_cache off; + + server { + listen 8080; #Listen port + + #Upload json file + set $store_dir "/Users/liyong/Code/Lua/lua-rest/openresty/conf/upload_files/"; # 文件存储路径 + + #Default location + location / { + default_type text/html; + content_by_lua_block { + ngx.say("Default location") + } + } + + #Read body +# lua_need_request_body on; + location /test_get_body { + content_by_lua_block { + local data = ngx.req.get_body_data() + ngx.say("hello ", data) + } + } + + client_body_in_file_only on; + location /test { + content_by_lua_block { + function getFile(file_name) + local f = assert(io.open(file_name, 'r')) + local string = f:read("*all") + f:close() + return string + end + + ngx.req.read_body() + local data = ngx.req.get_body_data() + if nil == data then + local file_name = ngx.req.get_body_file() + ngx.say(">> temp file: ", file_name) + if file_name then + data = getFile(file_name) + end + end + + ngx.say("hello ", data) + } + } + + #C FFI + location /c_ffi { + content_by_lua_file /Users/liyong/Code/Lua/lua-rest/openresty/conf/c_ffi/add/test_ffi_temp_file.lua; + } + + #Upload json file + location /upload_json_file { + content_by_lua_file /Users/liyong/Code/Lua/lua-rest/openresty/conf/lua/upload_json_file.lua; + } + + #Upload image file + location /upload_image { + content_by_lua_file /Users/liyong/Code/Lua/lua-rest/openresty/conf/lua/upload_image.lua; + } + + #Upload dir + location /append_file_output { + default_type ""; + alias /Users/liyong/Code/Lua/lua-rest/openresty/conf/upload_files; + autoindex on; + autoindex_exact_size off; + autoindex_localtime on; + } + + #Set and get redis + location /set_get_redis { + content_by_lua_file /Users/liyong/Code/Lua/lua-rest/openresty/conf/lua/set_and_get_redis.lua; + } + + #Get image append task status + location = /get_image_append_task_status { + content_by_lua_file /Users/liyong/Code/Lua/lua-rest/openresty/conf/lua/get_image_append_task_status.lua; + } + + #Other locations + include extra/*.conf; + } +} diff --git a/file_upload/upload_image.lua b/file_upload/upload_image.lua new file mode 100644 index 0000000..771b047 --- /dev/null +++ b/file_upload/upload_image.lua @@ -0,0 +1,235 @@ +local upload = require "upload" +local uuid = require "uuid" +local redis = require "redis" +local cjson = require "cjson" + +local chunk_size = 5 -- should be set to 4096 or 8192 + -- for real-world settings + +local form, err = upload:new(chunk_size) + +local output_image_filename_uuid = uuid.generate(); + +-- set default task status +data_table = {} +data_table["status"] = "InProgress" +data_table["data"] = "null" + +response_table = {} +response_table['r'] = "true" +response_table['d'] = data_table +response_table['e'] = "null" + +local responseData = cjson.encode(response_table) +ngx.say(responseData) + +local red = redis:new() + +red:set_timeouts(1000, 1000, 1000) + +local ok, err = red:connect("127.0.0.1", 6379) +if not ok then + ngx.say("failed to connect: ", err) + return +end + +ok, err = red:set(output_image_filename_uuid, responseData) +if not ok then + ngx.say("failed to set uuid: ", err) + return +end +ngx.say("set result: ", ok) + +local res, err = red:get(output_image_filename_uuid) +if not res then + ngx.say("failed to get uuid: ", err) + return +end + +if res == ngx.null then + ngx.say("uuid not found.") + return +end + +ngx.say("get uuid: " .. output_image_filename_uuid .. " | value :" .. res) + + +if not form then + ngx.log(ngx.ERR, "failed to new upload: ", err) + ngx.say("failed to new upload: ", err) + ngx.exit(500) +end + +form:set_timeout(1000) -- 1 sec + +-- String split +string.split = function(s, p) + local rt= {} + string.gsub(s, '[^'..p..']+', function(w) table.insert(rt, w) end ) + return rt +end + +-- Get file trim +string.trim = function(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +-- Upload file save path config in nginx.conf +local saveRootPath = ngx.var.store_dir + +local fileToSave +local ret_save = false +local upload_image_filename +local save_image_filename + +local upload_image_table = {} +local upload_image_index = 1 + +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 + -- 开始读取 http header + -- 解析出本次上传的文件名 + local key = res[1] + local value = res[2] + if key == "Content-Disposition" then + -- 解析出本次上传的文件名 + -- form-data; name="testFileName"; filename="testfile.txt" + local kvlist = string.split(value, ';') + for _, kv in ipairs(kvlist) do + local seg = string.trim(kv) + if seg:find("filename") then + local kvfile = string.split(seg, "=") + upload_image_filename = string.sub(kvfile[2], 2, -2) + + ngx.say(" -->> POST : Upload origin image is ", upload_image_filename) + ngx.say("\n") + + if upload_image_filename then + -- Save file name with generate uuid + save_image_filename = uuid:generate() + save_image_filename = save_image_filename .. '.' .. upload_image_filename:match(".+%.(%w+)$") + fileToSave = io.open(saveRootPath .. save_image_filename, "w+") + if not fileToSave then + ngx.say(" Error: Failed to open file ", save_image_filename) + return + else + ngx.say("Open file ok ", save_image_filename) + ngx.say("\n") + + upload_image_table[upload_image_index] = saveRootPath .. save_image_filename .. " " + ngx.say("Insert upload image table "..upload_image_index.." with "..upload_image_table[upload_image_index]) + ngx.say("\n") + + upload_image_index = upload_image_index + 1 + 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("Show all upload files\n") + + -- Show all upload files + upload_image_index = upload_image_index -1 + for i = 1, upload_image_index do + ngx.say("Save upload file is : " .. upload_image_table[i]) + ngx.say("\n") + end + + image_append_coroutine = coroutine.create( + function () + -- Append images + -- ngx.say("Upload image number is : " , upload_image_index ) + local append_images_path + append_images_path = table.concat(upload_image_table) + ngx.say("Input images list : " , append_images_path) + ngx.say("\n") + +-- local append_output_image = saveRootPath .. uuid.generate()..".jpg "; + local append_output_image = saveRootPath .. output_image_filename_uuid..".jpg "; + ngx.say("Output image is : "..append_output_image) + ngx.say("\n") + + -- Debug + ngx.say('convert -append '..append_images_path..' '..append_output_image) + ngx.say("\n") + + local call_imagemagick_cmd = io.popen('convert -append '..append_images_path..' '..append_output_image) + local imagemagick_cmd_replay = call_imagemagick_cmd:read("*all") + ngx.say(imagemagick_cmd_replay) + + -- set default task status + data_table = {} + data_table["status"] = "Done" + data_table["data"] = output_image_filename_uuid + + response_table = {} + response_table['r'] = "true" + response_table['d'] = data_table + response_table['e'] = "null" + + local responseData = cjson.encode(response_table) + ngx.say(responseData) + + local red = redis:new() + + red:set_timeouts(1000, 1000, 1000) + + local ok, err = red:connect("127.0.0.1", 6379) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ok, err = red:set(output_image_filename_uuid, responseData) + if not ok then + ngx.say("failed to set uuid: ", err) + return + end + ngx.say("set result: ", ok) + + local res, err = red:get(output_image_filename_uuid) + if not res then + ngx.say("failed to get uuid: ", err) + return + end + + if res == ngx.null then + ngx.say("uuid not found.") + return + end + + ngx.say("uuid: ", res) + + end + ) + + coroutine.resume(image_append_coroutine) + +end \ No newline at end of file