nginx上传文件

本文探讨了在nginx中处理大文件上传的方案,包括nginx-upload-module、nginx-big-upload和lua-resty-upload。其中,lua-resty-upload适用于RAW文件上传,并提供了线程安全的分块上传方式,但不支持多部分POST请求。此外,还提到了clientbodyinfileonly配置选项在文件上传中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

nginx上传文件

主要包括以下四种方法:

nginx-upload-module

已经用于生产环境,安装需要编译nginx。
主要的配置参数:
upload_pass 指明了需要后续处理的php地址
upload_cleanup 如果php出现400 404 499 500-505之类的错误,则删除上传的文件
upload_store 上传文件存放地址
upload_store_access 上传文件的访问权限,user:r是指用户可读
upload_limit_rate 上传限速,如果设置为0则表示不限制
upload_pass_form_field 从表单原样转到后端的参数,可以正则表达式表示
官方的例子是upload_pass_form_field "^submit$|^description$";
意思是把submit,description这两个字段也原样通过upload_pass传递到后端php处理。如果希望把所有的 表单字段都传给后端可以用upload_pass_f orm_field "^.*$";

upload_set_form_field可以使用的几个变量
    $upload_field_name    表单的name值
    $upload_content_type    上传文件的类型
    $upload_file_name    客户端上传的原始文件名称
    $upload_tmp_path    文件上传后保存在服务端的位置

upload_aggregate_form_field 可以多使用的几个变量,文件接收完毕后生成的
    $upload_file_md5    文件的MD5校验值
    $upload_file_md5_uc    大写字母表示的MD5校验值
    $upload_file_sha1    文件的SHA1校验值
    $upload_file_sha1_uc    大写字母表示的SHA1校验值
    $upload_file_crc32    16进制表示的文件CRC32值
    $upload_file_size    文件大小


需要在nginx.conf文件中配置,如下:
location /upload {
        # 文件上传以后转给后端的PHP代码去处理
        upload_pass /movefile.php;

        # 上传的文件临时存储位置
        # 此处注意,我把临时文件目录放到了tmpfs中,为了速度,但有丢失数据的风险!
        upload_store /dev/shm;
        
        # Allow uploaded files to be read only by user
        upload_store_access user:r;

        # Set specified fields in request body
        upload_set_form_field $upload_field_name.name "$upload_file_name";
        upload_set_form_field $upload_field_name.content_type "$upload_content_type";
        upload_set_form_field $upload_field_name.path "$upload_tmp_path";


        # Inform backend about hash and size of a file
        upload_aggregate_form_field "$upload_field_name.md5" "$upload_file_md5";
        upload_aggregate_form_field "$upload_field_name.size" "$upload_file_size";

        upload_pass_form_field "^submit$|^description$";

        upload_cleanup 400 404 499 500-505;
        }

nginx-big-upload

该module与nginx-upload-module主要区别:
  • Linear resumability - there is no way to upload last chunk as first in row, thus there is no risk of bomb file DoS attack. Chunks must be uploaded sequentially, therefore there is also no need to keep fragments layout (.status files) on server.
  • nginx-upload-module doesn't work currently with nginx 1.3.9 and newer, see #41.
  • Easy to enhance/fork, Lua modules are easy to develop, it took me 2 days to learn Lua and create first production version.
  • Multi-part POST requests (form uploads) are not supported only RAW file in PUT/POST request; check lua-resty-upload;
  • No upload rate limit setting - only one client can upload a given file so it is better to throttle downloads.
  • nginx-upload-module doesn't provide CRC32 or SHA1 calculation in resumable mode.
安装和使用请查看github上的文档: https://github.com/pgaertig/nginx-big-upload

lua-resty-upload

https://github.com/openresty/lua-resty-upload

主要依赖一个upload.lua,所以自然需要安装lua执行环境和nginx-lua,例子如下:

nginx.conf配置文件:
 location /uploadfile{
              
                content_by_lua_file 'conf/lua/savefile.lua';
        }

只需要自己写一个处理文件

package.path = '/usr/local/share/lua/5.1/?.lua;'
package.cpath = '/usr/local/lib/lua/5.1/?.so;'
local upload = require "upload"  

local chunk_size = 8192
local form = upload:new(chunk_size) 

local file  
local filename
local osfilepath = /tmp/

local filelen=0

form:set_timeout(1000) -- 1 sec  



while true do  
    local typ, res, err = form:read()  
    if not typ then  
        return  
    end  
    if typ == "header" then  
        if res[1] ~= "Content-Type" then  
            oldfilename = get_filename(res[2])
			
            if oldfilename then  
				newfilename = string.gsub(string.gsub(string.gsub(oldfilename,'%(',''),'%)',''),' ','')
                filepath = osfilepath  .. newfilename  
                file = io.open(filepath,"w+")  
                if not file then     
                    return  
                end
				
            else  
            end  
        end  
    elseif typ == "body" then  
        if file then  
            filelen= tonumber(string.len(res))      
            file:write(res)  
        else  
        end  
    elseif typ == "part_end" then  	
        if file then
            file:close()  
            file = nil
	end
		
    elseif typ == "eof" then 
        break  
    else  
    end 
end

clientbodyinfileonly















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值