所以我默认上传 1Mb block ,并且一次同时上传 5 个 block ,但是在这些 block 完成后,我的客户端不会发送剩余的 block 。因此最大输出为 5Mb,有人知道为什么吗?我没有更改任何其他默认设置,testChunks 已启用。
我的 Node 侧帖子是根据 smartsprocket 的答案建模的:
reassemble binary after flow.js upload on node/express server
我的获取方基于:
//'found', filename, original_filename, identifier
//'not_found', null, null, null
$.get = function(req, callback) {
var chunkNumber = req.param('flowChunkNumber', 0);
var chunkSize = req.param('flowChunkSize', 0);
var totalSize = req.param('flowTotalSize', 0);
var identifier = req.param('flowIdentifier', "");
var filename = req.param('flowFilename', "");
if (validateRequest(chunkNumber, chunkSize, totalSize, identifier, filename) == 'valid') {
var chunkFilename = getChunkFilename(chunkNumber, identifier);
fs.exists(chunkFilename, function(exists) {
if (exists) {
callback('found', chunkFilename, filename, identifier);
} else {
callback('not_found', null, null, null);
}
});
} else {
callback('not_found', null, null, null);
}
};
我不明白为什么它没有再次触发,流程如下:尝试获取文件 block ,无 block ,回复 404,POST CHUNK,POST PARTLY_DONE。 (每次同时上传 x5)。 然后它不再上传 block ,它只是在某些部分停止(许多console.logs还没有解决这个问题)。
我已经从永久性错误中删除了 404,这样应用程序就不会停止,但它仍然会停止。
任何帮助都会很棒,因为文件有时可能大于 5Mb。
谢谢, 乔
编辑(完整邮政编码):
客户端设置(仅更改 mg-flow 的默认设置):
chunkSize: 1024 * 1024,
forceChunkSize: false,
simultaneousUploads: 5,
singleFile: false,
fileParameterName: 'file',
progressCallbacksInterval: 0, //instant feedback
speedSmoothingFactor: 1,
query: {},
headers: {},
withCredentials: false,
preprocess: null,
method: 'multipart',
prioritizeFirstAndLastChunk: false,
target: '/',
testChunks: true,
generateUniqueIdentifier: null,
maxChunkRetries: undefined,
chunkRetryInterval: undefined,
permanentErrors: [415, 500, 501],
onDropStopPropagation: false
通过将 target 选项设置为 url,在标签中动态设置目标,这是范围内动态创建的变量,因此它会上传到 tmp,然后在所有 block 接收到讲座目录后移动,以使组织和管理更容易,例如删除
i.e. uploadFile/{{module.id}}/{{lecture.id}}
然后是服务器端,
var multipart = require('connect-multiparty');
var multipartMiddleware = multipart();
获取
//Handle status checks on chunks through Flow.js
app.get('/uploadFile/:mId/:id', lectureRoutes.fileGet);
exports.fileGet = function(req, res) {
flow.get(req, function(status, filename, original_filename, identifier) {
console.log('GET', status);
res.send(200, (status == 'found' ? 200 : 404));
});
}
//'found', filename, original_filename, identifier
//'not_found', null, null, null
$.get = function(req, callback) {
var chunkNumber = req.param('flowChunkNumber', 0);
var chunkSize = req.param('flowChunkSize', 0);
var totalSize = req.param('flowTotalSize', 0);
var identifier = req.param('flowIdentifier', "");
var filename = req.param('flowFilename', "");
if (validateRequest(chunkNumber, chunkSize, totalSize, identifier, filename) == 'valid') {
var chunkFilename = getChunkFilename(chunkNumber, identifier);
fs.exists(chunkFilename, function(exists) {
if (exists) {
callback('found', chunkFilename, filename, identifier);
} else {
callback('not_found', null, null, null);
}
});
} else {
callback('not_found', null, null, null);
}
};
发布
//To Save File
app.post('/uploadFile/:mId/:id', multipartMiddleware, lectureRoutes.fileAddPost);
//FIX THIS
exports.fileAddPost = function(req,res){
flow.post(req, function(status, filename, original_filename, identifier, currentTestChunk, numberOfChunks) {
console.log('POST', status, original_filename, identifier);
if (status === 'done' && currentTestChunk > numberOfChunks) {
var stream = fs.createWriteStream('./tmp/' + filename);
//EDIT: I removed options {end: true} because it isn't needed
//and added {onDone: flow.clean} to remove the chunks after writing
//the file.
flow.write(identifier, stream, {onDone: flow.clean});
//Once written move the file.
mv('./tmp/'+filename,'./public/files/'+req.params.mId+'/'+req.params.id+'/'+filename, {mkdirp: true,clobber: false}, function(err){
if(err == 'EEXIST') {
//FILE ALREADY EXIST STOP IT FROM BEING RE-ADDED TO DB, although allow file to be moved incase its newer
}
else if(!err){
var set = {};
Modules.findById(req.params.mId, function(err,module){
module.Lectures.id(req.params.id).Files.push({"fileName" : filename});
module.save(function(err){
if(err) console.log(err)
//return id of file back
else{
var link = module.Lectures.id(req.params.id).Files;
res.send(200, link[link.length-1]._id)
}
})
})
}
});
}
});
}
//'partly_done', filename, original_filename, identifier
//'done', filename, original_filename, identifier
//'invalid_flow_request', null, null, null
//'non_flow_request', null, null, null
$.post = function(req, callback){
var fields = req.body;
var files = req.files;
var chunkNumber = fields['flowChunkNumber'];
var chunkSize = fields['flowChunkSize'];
var totalSize = fields['flowTotalSize'];
var identifier = cleanIdentifier(fields['flowIdentifier']);
var filename = fields['flowFilename'];
var original_filename = fields['flowIdentifier'];
if (!files[$.fileParameterName] || !files[$.fileParameterName].size) {
callback('invalid_flow_request', null, null, null);
return;
}
var validation = validateRequest(chunkNumber, chunkSize, totalSize, identifier, filename, files[$.fileParameterName].size);
if (validation == 'valid') {
var chunkFilename = getChunkFilename(chunkNumber, identifier);
fs.rename(files[$.fileParameterName].path, chunkFilename, function(){
// Do we have all the chunks?
var currentTestChunk = 1;
var numberOfChunks = Math.max(Math.floor(totalSize/(chunkSize*1.0)), 1);
var testChunkExists = function(){
fs.exists(getChunkFilename(currentTestChunk, identifier), function(exists){
currentTestChunk++;
if(exists){
if(currentTestChunk>numberOfChunks) {
callback('done', filename, original_filename, identifier, currentTestChunk, numberOfChunks);
} else {
// Recursion
testChunkExists();
}
} else {
//Add currentTestChunk and numberOfChunks to the callback
callback('partly_done', filename, original_filename, identifier, currentTestChunk, numberOfChunks);
}
});
}
testChunkExists();
});
} else {
callback(validation, filename, original_filename, identifier);
}
}
最佳答案
您在 flow.write 之后调用 mv()
但应在 flow.write 的回调中调用它。 mv()
在 flow.write 完成之前被调用,并且因为您的 res.send 在此函数中,所以它没有完成。
尝试将 res.send 移动到 flow.post 调用的顶部,看看是否获得了所有 block 。
exports.fileAddPost = function(req,res){
flow.post(req, function(status, filename, original_filename, identifier, currentTestChunk, numberOfChunks) {
console.log('POST', status, original_filename, identifier);
res.send(200);
...
}
如果有效,则可能是因为 mv()
不在回调中。将其移至回调中,但暂时将 res.send 保留在原处。
exports.fileAddPost = function(req,res){
flow.post(req, function(status, filename, original_filename, identifier, currentTestChunk, numberOfChunks) {
...
flow.write(identifier, stream, { onDone: flow.clean }, function(err) {
if (err) {
console.log(err);
}
else {
//call mv() here
}
});
然后在 flow.write ($.write) 中为其签名添加回调。
$.write = function(identifier, writableStream, options, callback) {
...
//At the bottom of this function, after calling options.onDone(identifier)
if (options.onDone) {
options.onDone(identifier);
{
return callback(null);
您还应该添加错误处理。在 if (exists) { ... }
之后,您可以添加一个 else if((!exists) && number === 1) { return callback('Cannot write file from chunks, chunks don\t exit.');
然后在这之后将是 else
block 。
现在尝试一下,看看是否一切正常。如果有效,请尝试将 res.send 移回到您的 mv()
函数中。如果它不起作用,那么这个函数可能不是异步的。
关于javascript - 如果大于 5MB,Flow.js(在 Angular.js 中)上传到 node.js 将失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25274339/