文件上传从tornado迁移到nginx upload module

工作中几个场景涉及到文件上传,原来的解决方案是由tornado直接处理带文件(multipart-form)的http请求,但是文件有些文件过大,超过100M,再由tornado来处理有些不合适,stackoverflow有评论指出tornado把文件读到一个StringIO中,这样是有风险的,另外tornado只用来处理大文件上传也不是一个优雅的做法,这种事情还是有nginx来做的好,所以文件上传迁移到nginx upload module。

nginx upload 模块的安装

下载nginx upload module,截止到1月27,建议下载github上2.2分支的源码,我从其官网下载2.2.0版本源码编译时有问题,直接从github拖代码下来编译正常。

找到原来nginx所在路径,比如/usr/local/nginx,查看当前安装的编译参数:/usr/local/nginx/sbin/nginx -V,然后进入nginx源码目录,执行configure,除了加上已有的参数外,再加上:

--add-module=/path/to/upload/module

然后执行make && make install完成安装。

nginx upload module 配置

再nginx配置文件的server节点增加如下配置,假设http://hostname/upload地址用户文件上传。

location /upload {
    upload_pass /api/upload;
    upload_cleanup 400 404 499 500-505;
    upload_store /tmp/upload_tmp;
    upload_store_access user:r;
    upload_limit_rate 0;
    upload_set_form_field "file_name" $upload_file_name;
    upload_set_form_field "content_type" $upload_content_type;
    upload_set_form_field "tmp_path" $upload_tmp_path;
    upload_aggregate_form_field "md5" $upload_file_md5;
    upload_aggregate_form_field "size" $upload_file_size;
    upload_pass_form_field "^.*$";
}

基本配置如下:

upload_pass 指明了需要后续处理的php/tornado地址

upload_cleanup 如果php出现400 404 499 500-505之类的错误,则删除上传的文件

upload_store 上传文件存放地址

upload_store_access 上传文件的访问权限,user:r是指用户可读

upload_limit_rate 上传限速,如果设置为0则表示不限制

upload_set_form_field 设定额外的表单字段。这里有几个可用的变量:

$upload_file_name 文件原始名字

$upload_field_name 表单的name值

$upload_content_type 文件的类型

$upload_tmp_path 文件上传后的地址

upload_aggregate_form_field 额外的变量,在上传成功后生成

$upload_file_md5 文件的MD5校验值

$upload_file_size 文件大小

upload_pass_form_field 从表单原样转到后端的参数,可以正则表达式表示。官方的例子是upload_pass_form_field "^submit$|^description$";意思是把submit,description这两个字段也原样通过upload_pass传递到后端php处理。如果希望把所有的表单字段都传给后端可以用upload_pass_form_field "^.*$";

可以看到,我们上传文件存储到临时目录后nginx立即会向后面的tornado服务的/api/upload发起一个表单请求,其中有五个表单项:

  • file_name 上传的文件名
  • content_type 文件的MIME类型
  • tmp_path 临时文件目录
  • md5 文件的md5值
  • size 文件大小

这时就已经可以在tornado中对文件进行处理了。

tornado对文件的后续处理

代码如下:

def upload(self):
    file_name = self.get_argument("file_name")
    tmp_path = self.get_argument("tmp_path")
    do_some_thing(tmp_path)
    self.finish("file uploaded!")

几个注意事项

  1. 最好从github上的2.2分支直接拉代码下来进行编译,如果采用官网给的2.2下载编译可能会有问题;
  2. nginx中的location配置项的地址不要和里面的upload_pass项相同,否则tornado不会收到请求。

-------------------2015-02-01-------------------

http://www.grid.net.ru/nginx/upload.en.html

How to use

Download sources from one of the links above. Unpack the archive:

tar xvzf nginx_upload_module-2.2.0.tar.gz

Configure nginx with additional module:

For nginx versions other than 0.7.44-51:
cd <path to nginx sources>
./configure --add-module=<path to upload module sources>
make
make install
For nginx versions 0.7.44-51:
cd <path to nginx sources>
CFLAGS="-Dnginx_version=7052" ./configure --add-module=<path to upload module sources>
make
make install

你可能感兴趣的:(文件上传从tornado迁移到nginx upload module)