course_upload.lua 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. -- =========================================
  2. -- 文件上传接口
  3. -- =========================================
  4. local upload = require "resty.upload"
  5. local cjson = require "cjson.safe"
  6. ngx.header.content_type = "application/json; charset=utf-8"
  7. local upload_dir = "/opt/oss/upload/"
  8. local max_size = 20 * 1024 * 1024 -- 20MB
  9. -- 工具函数
  10. local function now_ms()
  11. return tostring(math.floor(ngx.now() * 1000))
  12. end
  13. local function get_ym()
  14. return os.date("%Y%m")
  15. end
  16. local function safe_suffix(name)
  17. -- 获取文件后缀,例如 .png
  18. return name:match("^.+(%..+)$") or ""
  19. end
  20. local form, err = upload:new(4096)
  21. if not form then
  22. ngx.say(cjson.encode({ code = 500, msg = "创建上传对象失败: " .. (err or ""), data = {} }))
  23. return
  24. end
  25. form:set_timeout(10000)
  26. local file, filename, filesize = nil, nil, 0
  27. while true do
  28. local typ, res, err = form:read()
  29. if not typ then
  30. ngx.say(cjson.encode({ code = 500, msg = "读取上传内容失败: " .. (err or ""), data = {} }))
  31. return
  32. end
  33. if typ == "header" then
  34. local name, value = res[1], res[2]
  35. if name == "Content-Disposition" then
  36. local orig_name = value:match('filename="(.-)"')
  37. if orig_name then
  38. local suffix = safe_suffix(orig_name)
  39. local newname = get_ym() .. "_" .. now_ms() .. suffix
  40. local fullpath = upload_dir .. newname
  41. -- 判断文件是否存在
  42. local f = io.open(fullpath, "r")
  43. if f then
  44. f:close()
  45. ngx.say(cjson.encode({code = 429, msg = "当前访问人数较多,请稍后重试", data = {}}))
  46. return
  47. end
  48. -- 打开文件写入
  49. file, err = io.open(fullpath, "w+")
  50. if not file then
  51. ngx.say(cjson.encode({ code = 500, msg = "无法创建文件: " .. (err or ""), data = {} }))
  52. return
  53. end
  54. filename = newname
  55. end
  56. end
  57. elseif typ == "body" then
  58. if file then
  59. filesize = filesize + #res
  60. if filesize > max_size then
  61. file:close()
  62. os.remove(upload_dir .. filename)
  63. ngx.say(cjson.encode({ code = 413, msg = "文件过大(限制20MB)", data = {} }))
  64. return
  65. end
  66. file:write(res)
  67. end
  68. elseif typ == "part_end" then
  69. if file then
  70. file:close()
  71. file = nil
  72. end
  73. elseif typ == "eof" then
  74. break
  75. end
  76. end
  77. ngx.say(cjson.encode({
  78. code = 200,
  79. msg = "上传成功",
  80. data = {
  81. filename = filename,
  82. url = "/oss/upload/" .. filename,
  83. size = filesize
  84. }
  85. }))