使用nginx实现大文件上传
September 9, 2018
背景
两台外网服务器之间需要传输一个较大的文件,目标服务器有webserver。
解决方案
初步想了下,有几种思路:
- ftp:目标服务器搭建ftp。通过ftp client上传。部署成本太高(主要是懒),放弃
- nginx-upload-module: 较为理想的方案,使用nginx插件支持,成本小。但在编译module时卡住了,忘了之前的编译选项,加入upload module之后编译又报错,不想太折腾,放弃了。
- 在webserver上自己实现file upload server:此方案看似成本高,翻了一下,其实还挺简单。那就动手吧
流程
http upload server搭建
方法有很多,搭建webserver第一个想到的就是node了。于是找到了express-fileupload。npm库上代码都是现成的。
[text]
const express = require('express');
const fileUpload = require('express-fileupload');
const app = express();
// default options
app.use(fileUpload());
app.post('/upload', function(req, res) {
if (!req.files)
return res.status(400).send('No files were uploaded.');
// The name of the input field (i.e. "sampleFile") is used to retrieve the uploaded file
let sampleFile = req.files.sampleFile;
// Use the mv() method to place the file somewhere on your server
sampleFile.mv('/somewhere/on/your/server/filename.jpg', function(err) {
if (err)
return res.status(500).send(err);
res.send('File uploaded!');
});
});
// app.listen(8080);
nginx路由
反向代理增加路由配置:
[text]
location /upload {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
并设置最大包大小,否则文件过大会被ng拒绝413 (Request Entity Too Large)。
[text]
client_max_body_size 200m;
上传
使用curl模拟表单上传:
[text]
curl -F 'sampleFile=@path/to/local/file' UPLOAD_ADDRESS
curl支持一次上传多个,不过upload server实现得修改支持命名。
其他
线上上传时发现上传还是失败了,因为文件太大,导致node进程OOM kill了。。
不想在折腾了,直接用split把文件切成几个小文件后上传,然后再到目标机器使用cat合并。
[text]
# binary拆分成多个20m的文件,输出文件名类似outputSerial_aa, outputSerial_ab, outputSerial_ac....
split -b 20m uploadfile outputSerial_
在目标机器执行合并操作:
[text]
cat outputSerial_* > uploadfile
总结起来,对比重编ng貌似也不简单:P)。。
See all postsSee all posts