nginx+lua file upload summary (available for pro test)

Posted by jammyjames on Fri, 17 Dec 2021 03:41:07 +0100

1, Requirement description

The front end often needs to add some templates jpg, and then re send them to production; Therefore, a function is added to allow users to upload templates jpg to the front-end server.
The front-end project is located on the front-end server with nginx; In order to realize the function, it is not appropriate to install another jdk+java background code, so nginx+lua is used to realize the file upload function.

2, Specific process

1. Access the front-end server, such as http://10.123.123.123 At this time, the welcome page of nginx appears. If Welcome to OpenResty is installed, it means resty is installed (this software includes nginx function), so the environment is basically OK; If you are installing normal nginx, you may need to reinstall it as openresty.

2. Modify the configuration information of resty(nginx), such as / home / appadmin / nginx / conf / nginx Conf, add a path for uploading files. The example is as follows:

location /uploadFile {
  error_log logs/upload.err.log;
  #if ($remote_addr !~* "^10\.13(0|3)\.(.*)\.(.*)$") { echo "ip wrong!"; }
  #set $home_path "/home/appadmin/uploadFile";
  #set $sub_path $head_sub_path;
  #lua_code_cache off;
  content_by_lua_file conf/luascript/upfile.lua;
}

explain:
(1) The annotated home_path means that the path saved after file upload can be configured here, and the subsequent lua files can take the value here.
(2) The annotated sub_path means that you can read a path (set by the front end) from the request header head_sub_path, and then use this variable to splice the secondary path saved by the uploaded file.
(3) The last sentence is to connect to upfile.lua for subsequent processing.

3. Create an upfile Lua, put it in the specified location, such as / home / appadmin / nginx / conf / luascript / upfile Lua, the contents of the file are as follows:

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)

string.split = function(s,p)
  local rt = {}
  string.gsub(s,'[^'..p..']+', function(w) table.insert(rt, w) end)
  return rt
end

-- FILE LOCATION
local saveRootPath = "/home/appadmin/uploadFile/"

local fileToSave

local ret_save = false

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
    -- read fileName from 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, "=")
            local filename = string.sub(kvfile[2], 2, -2)
           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
  else if typ == "body" then
    if fileToSave then
      fileToSave:write(res)
    end
  else if 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("save file ok")
end


4. Create an html file to test, such as / home / appadmin / nginx / html / myupload html, as follows:

<!DOCTYPE html>
<html>
<head>
<title>File Upload</title>
</head>

<body>
<form action="uploadFile" method="post" enctype="multipart/form-data">
<label for="testFileName">select file: </label>
<input type="file" name="testFileName" />
<input type="submit" name="upload" value="Upload" />
</form>
</body>
</html>

If it is written locally, the action can be written as:

action="http://10.123.123.123/uploadFile"

Directly access the path where nginx is located.

5. If the test is successful, a file will be returned with the content of save file ok, which is configured in the lua file. Then you can see the uploaded file in the corresponding path of the server. This is the end;

If an error is reported, continue to look down.

6. If you find upload err. The log file contains the error message after uploading the file (configured by nginx above):

(1) If an error is reported, resty cannot be found Upload. The solution is as follows:
Use the find command to find whether there is upload Lua documents;
If yes, copy this file to the path prompted in the error message;
(the first sentence of the error report will prompt that the upload.lua file is not found in a path);

If there is no upload Lua files need to be installed, such as lua-resty-upload-0.10. Refer to the following or Baidu for installation methods.

(2) If an error is reported, cjson / cjson. Is not found lua/cjson. So, the solution is as follows:
You can install lua-cjson-2.1 0.6.

1.) first use the find command to check whether there is cjson, because if the rest version of nginx is installed, there may be files under [/ home/appamin/nginx-1.13.6.2/build/bundle/lua-cjson-2.1.0.6], and cd to this path.
1.5.) Download this tar from the Internet GZ package. Decompress the cd to this path.
2.)vi Makefile, where the installation path can be modified; Because you may not have permission to install to the default path, modify:

#PREFIX = /usr/local
PREFIX = $(HOME)/lua

Exit vi after saving.
3.) execute the make command (the Makefile file will be read and compiled); If an error is reported, lua cannot be found H file, you need to install lua, such as LuaJIT-2.1-20180420. After installation, find the file with find and copy it to the path prompted by the error message (if you do not have permission during installation, you can also modify the installation path); Re execute the make command.

4.) execute the make install command. After the installation is successful, you can find cjson So file.

5.) put cjson The so is copied to the error message, prompting that cjson is not found So path. (forget cjson/cjson.lua, just have cjson.so)

7. Test the upload function again. It should be successful.

(if there are any errors, you can leave a message and discuss and solve them together)

3, Summary

1.nginx should use the openresty version.
2. Modify nginx Conf, add a path.
3. Write lua files to upload files.
4. Write front-end html for self-test.

5. The file deletion function can also be realized by nginx+lua, which is mainly to write lua for follow-up research.