通过lua-resty-upload实现文件上传的例子,


1、采用openresty中一个lua-resty-upload模块实现基于rfc1867的http协议文件上传、要求客户端提交的表单enctype=”multipart/form-data”,method=”POST”。最下面有发送请求的代码。
2、关于http文件上传可参考[[http://www.faqs.org/rfcs/rfc1867.html]]
或者[[http://blog.csdn.net/xiaoxiaohai123/article/details/2538857]]
3、具体的上传策略等可根据具体业务定制、此处不表。

4、以下是一个文件通过代理节点、上传到源站的例子

假如用户的源站在10.1.7.12, 代理节点是10.1.7.13, (当然不通过代理也可以,即直接上传到目的地;通过代理的话,可以绕开直连网络不通的问题,或者类似于借助于cdn的节点上传内容到源站)

1 则10.1.7.13的配置大体为:nginx的其他配置已忽略

localtion /uploadlua {
            rewrite_by_lua_file         "conf/lua/rewrite.lua";
            access_by_lua_file          "conf/lua/access.lua";
            header_filter_by_lua_file   "conf/lua/header_filter.lua";
            proxy_pass http://10.1.7.12;#实现文件上传消息的转发
}

2 则源站10.1.7.12的配置为:

localtion /uploadlua {
          rewrite_by_lua_file         "conf/lua/rewrite.lua";
          access_by_lua_file          "conf/lua/access.lua";
          content_by_lua_file "conf/lua/content_upload2file.lua";
}

3 content_by_lua_file即是通过lua-resty-upload实现的解析http协议读取内容,并存入目的

local resty_md5 = require "resty.md5"
local upload = require "resty.upload"
local str = require "resty.string"
local dst_dir = "/tmp/upload"

function get_filename(res)  
    local filename = ngx.re.match(res,'(.+)filename="(.+)"(.*)')  
    if filename then   
        return filename[2]  
    end  
end  

function handle_uploading()
    local chunk_size = 500*1024 
    local form, err = upload:new(chunk_size)
    if not form then
        ngx.log(ngx.ERR, "failed to new upload: ", err)
        ngx.exit(500)
    end
    local md5 = resty_md5:new()
    file_name = ""
    file = nil
    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
            file_name = get_filename(res[2])
            if file_name then
                file = io.open(dst_dir .. "/" .. file_name, "w+")
                if not file then
                    ngx.say("failed to open file ", file_name)
                    return
                end
            end

         elseif typ == "body" then
            if file then
                file:write(res)
                md5:update(res)
            end

        elseif typ == "part_end" then
            if file then
                file:close()
                file = nil
            end
            local md5_sum = md5:final()
            md5:reset()
            ngx.log(ngx.ERR, "md5:", str.to_hex(md5_sum))
            ngx.say("md5:",  str.to_hex(md5_sum))

        elseif typ == "eof" then
            break

        else
            -- do nothing
        end
    end
    if file_name then
       return dst_dir .. "/" .. file_name
    else 
       return  "filename not get"
    end
end

handle_uploading()

4 通过python的requests发送客户端上传请求

\#coding=utf-8
import os
import requests
url = 'http://www.abcde.com/uploadlua'

path = u'/uploading/testfile.txt'
http_proxy  = "http://10.1.7.13" #此处如果修改为10.1.7.12则表示直接向源站上传

proxyDict = { 
              "http"  : http_proxy, 
            }
print path
files = {'file': open(path, 'rb')}
print "file: ", path
print "size: ", os.path.getsize(path) 
r = requests.post(url, files=files, proxies=proxyDict)
print r.url,r.text

相关内容

    暂无相关文章