在 OpenResty(基于 Nginx + Lua)中读取 HTTP 请求的 body_data
,可以使用 ngx.req.read_body()
和 ngx.req.get_body_data()
。以下是详细方法和注意事项:
1. 基础读取方法
location /upload {
content_by_lua_block {
-- 必须先调用 read_body() 才能获取 body_data
ngx.req.read_body()
-- 获取请求体数据
local body_data = ngx.req.get_body_data()
if not body_data then
ngx.say("Error: Failed to read request body")
return ngx.exit(400)
end
-- 打印 body 内容(调试用)
ngx.say("Body data: ", body_data)
}
}
2. 处理大文件(内存 vs 临时文件)
默认情况:OpenResty 会将小请求体缓存在内存中,大文件会写入临时文件。
强制全部读入内存:
-- 在 nginx.conf 的 http/server/location 中设置
client_max_body_size 50m; --允许最大50MB请求体
client_body_buffer_size 50m; --内存缓冲区大小设为50MB
从临时文件中读取: 如果请求体超过
client_body_buffer_size
,数据会被存入临时文件,需通过ngx.req.get_body_file()
获取路径:
local temp_file = ngx.req.get_body_file()
if temp_file then
local file = io.open(temp_file, "rb")
local body_data = file:read("*a")
file:close()
end
3. JSON/FormData解析示例
(1)解析 JSON Body:
local cjson = require "cjson.safe"
ngx.req.read_body()
local json_str = ngx.req.get_body_data()
local data = cjson.decode(json_str)
if not data then
ngx.say("Invalid JSON")
return ngx.exit(400)
end
-- 使用 data.key1, data.key2...
(2)解析 Multipart FormData:
推荐使用第三方库如 lua-resty-upload:
local upload = require "resty.upload"
local form = upload:new()
while true do
local typ, res, err = form:read()
if not typ then break end
if typ == "file" then
-- res是文件名,err是文件内容块
ngx.say("File chunk received")
elseif typ == "form" then
-- res是字段名,err是字段值
ngx.say("Form field: ", res, "=", err)
end
end
4.常见问题排查
(1)返回 nil
的可能原因:
- ❌未调用
ngx.req.read_body()
- ❌请求体超过
client_body_buffer_size
且未处理临时文件
- ❌客户端未正确发送数据(检查前端代码)
(2)性能优化建议:
# nginx.conf优化项:
http {
lua_need_request_body on; #预读body到内存
}
完整上传文件示例
location /upload {
client_max_body_size 100m;
content_by_lua_block {
local upload = require "resty.upload"
--初始化上传处理器
local form = upload:new()
while true do
local typ, res, err= form:read()
if not typ then break end
if typ=="file" and res=="file1" then
local path="/tmp/"..err.filename
local file=io.open(path,"wb")
while true do
local chunk=form:read()
if not chunk or chunk==0 then break end
file:write(chunk)
end
file:close()
ngx.say("Saved:",path)
end
end
}
}
如果需要更具体的场景分析,可以提供以下信息:
1.你的Nginx/OpenResty版本 (nginx -V
)
2.前端发送的具体代码片段
内容由零声教学AI助手提供,问题来源于学员提问