如何阻止 Express.js 重复长的多部分请求?
What to do to stop Express.js from duplicating long multipart requests?
考虑以下代码:
var routes = function(app) {
app.post('/api/video', passport.authenticate('token', authentication), video.createVideo);
}
function createVideo(request, response) {
logger.info('starting create video');
upload(request, response, function(err) {
logger.info('upload finished', err);
//callback omitted for brevity
}
}
使用 multer-s3 中间件上传 multer:
var upload = multer({
storage: s3({
dirname: config.apis.aws.dirname,
bucket: config.apis.aws.bucket,
secretAccessKey: config.apis.aws.secretAccessKey,
accessKeyId: config.apis.aws.accessKeyId,
region: config.apis.aws.region,
filename: function(req, file, cb) {
cb(null, req.user._id + '/' + uuid.v4() + path.extname(file.originalname));
}
}),
limits: {
fileSize: 1000000000
},
fileFilter: function(req, file, cb) {
if (!_.contains(facebookAllowedTypes, path.extname(file.originalname))) {
return cb(new Error('Only following types are allowed: ' + facebookAllowedTypes));
}
cb(null, true);
}
}).fields([{
name: 'video',
maxCount: 1
}]);
上面的代码执行以下操作:它获取从某处发送的文件并将其流式传输到 AWS S3 实例。 multer-s3 在后台使用 s3fs 创建写入流并将文件作为 5MB 多部分发送。
上传大文件(例如 300MB)可能需要几分钟时间。现在发生了一些非常奇怪的事情。我可以在我们的前端看到它只在 /api/video 上发送一个 POST 请求。其实我也试过用Postman发出请求,不信任我们的前端。
它开始上传,但大约 2 分钟后它开始第二次上传!如果我尝试上传较小的文件,例如 2-100MB,那么什么都不会发生。这是来自我的日志(来自上面的代码):
{"name":"test-app","hostname":"zawarudo","pid":16953,"level":30,"msg":"starting create video","time":"2015-12-02T14:08:22.243Z","src":{"file":"/home/areinu/dev/projects/test-app-uploader/backend/app/services/videoService.js","line":169,"func":"createVideo"},"v":0}
{"name":"test-app","hostname":"zawarudo","pid":16953,"level":30,"msg":"starting create video","time":"2015-12-02T14:10:28.794Z","src":{"file":"/home/areinu/dev/projects/test-app-uploader/backend/app/services/videoService.js","line":169,"func":"createVideo"},"v":0}
{"name":"test-app","hostname":"zawarudo","pid":16953,"level":30,"msg":"upload finished undefined","time":"2015-12-02T14:12:46.433Z","src":{"file":"/home/areinu/dev/projects/test-app-uploader/backend/app/services/videoService.js","line":171},"v":0}
{"name":"test-app","hostname":"zawarudo","pid":16953,"level":30,"msg":"upload finished undefined","time":"2015-12-02T14:12:49.627Z","src":{"file":"/home/areinu/dev/projects/test-app-uploader/backend/app/services/videoService.js","line":171},"v":0}
如您所见,两次上传都在几毫秒后结束,但第二次上传在 2 分钟后开始。问题是 - 应该只有一个上传!
我在邮递员中所做的只是设置我的访问令牌(所以护照授权我)并添加了一个文件。这应该只创建 1 个上传,同时发生 2 个,并且都上传相同的文件。
此外,请注意两个文件都已上传,都有不同的 uuid(注意文件名函数从 uuid 创建文件名),都出现在 s3 上,并且都有 300MB 的适当大小,都可以下载并且都可以使用.
如果上传较小,则不会发生重复。这种行为的原因是什么?如何解决?
问题很简单(我只花了一整天就弄明白了)。这只是节点请求的默认超时 - 2 分钟。我不知道为什么它会启动另一个,也不知道它为什么能正常工作,但是将我服务器上的默认超时设置为 10 分钟解决了这个问题。
如果有人知道为什么超时请求确实完成了(并且两次),请告诉我。那我会改进答案的。
考虑以下代码:
var routes = function(app) {
app.post('/api/video', passport.authenticate('token', authentication), video.createVideo);
}
function createVideo(request, response) {
logger.info('starting create video');
upload(request, response, function(err) {
logger.info('upload finished', err);
//callback omitted for brevity
}
}
使用 multer-s3 中间件上传 multer:
var upload = multer({
storage: s3({
dirname: config.apis.aws.dirname,
bucket: config.apis.aws.bucket,
secretAccessKey: config.apis.aws.secretAccessKey,
accessKeyId: config.apis.aws.accessKeyId,
region: config.apis.aws.region,
filename: function(req, file, cb) {
cb(null, req.user._id + '/' + uuid.v4() + path.extname(file.originalname));
}
}),
limits: {
fileSize: 1000000000
},
fileFilter: function(req, file, cb) {
if (!_.contains(facebookAllowedTypes, path.extname(file.originalname))) {
return cb(new Error('Only following types are allowed: ' + facebookAllowedTypes));
}
cb(null, true);
}
}).fields([{
name: 'video',
maxCount: 1
}]);
上面的代码执行以下操作:它获取从某处发送的文件并将其流式传输到 AWS S3 实例。 multer-s3 在后台使用 s3fs 创建写入流并将文件作为 5MB 多部分发送。
上传大文件(例如 300MB)可能需要几分钟时间。现在发生了一些非常奇怪的事情。我可以在我们的前端看到它只在 /api/video 上发送一个 POST 请求。其实我也试过用Postman发出请求,不信任我们的前端。
它开始上传,但大约 2 分钟后它开始第二次上传!如果我尝试上传较小的文件,例如 2-100MB,那么什么都不会发生。这是来自我的日志(来自上面的代码):
{"name":"test-app","hostname":"zawarudo","pid":16953,"level":30,"msg":"starting create video","time":"2015-12-02T14:08:22.243Z","src":{"file":"/home/areinu/dev/projects/test-app-uploader/backend/app/services/videoService.js","line":169,"func":"createVideo"},"v":0}
{"name":"test-app","hostname":"zawarudo","pid":16953,"level":30,"msg":"starting create video","time":"2015-12-02T14:10:28.794Z","src":{"file":"/home/areinu/dev/projects/test-app-uploader/backend/app/services/videoService.js","line":169,"func":"createVideo"},"v":0}
{"name":"test-app","hostname":"zawarudo","pid":16953,"level":30,"msg":"upload finished undefined","time":"2015-12-02T14:12:46.433Z","src":{"file":"/home/areinu/dev/projects/test-app-uploader/backend/app/services/videoService.js","line":171},"v":0}
{"name":"test-app","hostname":"zawarudo","pid":16953,"level":30,"msg":"upload finished undefined","time":"2015-12-02T14:12:49.627Z","src":{"file":"/home/areinu/dev/projects/test-app-uploader/backend/app/services/videoService.js","line":171},"v":0}
如您所见,两次上传都在几毫秒后结束,但第二次上传在 2 分钟后开始。问题是 - 应该只有一个上传!
我在邮递员中所做的只是设置我的访问令牌(所以护照授权我)并添加了一个文件。这应该只创建 1 个上传,同时发生 2 个,并且都上传相同的文件。
此外,请注意两个文件都已上传,都有不同的 uuid(注意文件名函数从 uuid 创建文件名),都出现在 s3 上,并且都有 300MB 的适当大小,都可以下载并且都可以使用.
如果上传较小,则不会发生重复。这种行为的原因是什么?如何解决?
问题很简单(我只花了一整天就弄明白了)。这只是节点请求的默认超时 - 2 分钟。我不知道为什么它会启动另一个,也不知道它为什么能正常工作,但是将我服务器上的默认超时设置为 10 分钟解决了这个问题。
如果有人知道为什么超时请求确实完成了(并且两次),请告诉我。那我会改进答案的。