ZBLOG

openResty读取body_data

在 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助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=23259

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?