我正在使用此代码进行文件更新:
app.post("/UploadFile", function(request, response)
{
var file = request.files.UploadedFile;
var name = request.param("Name");
var componentId = request.param("ComponentId");
console.log("Uploading: " + name);
var parameters =
{
filename: name,
metadata:
{
Type: "Screenshot",
ComponentId: componentId
}
};
grid.files.findOne( { "metadata.ComponentId" : componentId }, function(error, existing)
{
console.log("done finding");
if (error)
{
common.HandleError(error);
}
else
{
if (existing)
{
console.log("Exists: " + existing._id);
grid.remove({ _id: existing._id }, function(removeError)
{
if (removeError)
{
common.HandleError(removeError, response);
}
else
{
SaveFile(file, parameters, response);
}
});
}
else
{
console.log("new");
SaveFile(file, parameters, response);
}
}
});
});
function SaveFile(file, parameters, response)
{
console.log("Saving");
var stream = grid.createWriteStream(parameters);
fs.createReadStream(file.path).pipe(stream);
}
基本上我正在检查具有存储在元数据中的ID的文件。如果它存在,我在保存前删除它,如果不存在,我只是执行保存。它似乎只是偶尔起作用。我有时会看到两种错误的行为:
该文件将被删除,但不会重新创建。
该文件似乎已更新,但在我再次调用我的代码之前,它实际上不会被替换。所以基本上我需要做两个文件上传才能注册替换。
这是非常粗略的,我无法确定它是否能够起作用的模式。
所以我假设我做错了什么。使用gridfs-stream替换文件的正确方法是什么?
答案 0 :(得分:0)
很难从你提供的代码中确切地说出来(即你没有展示response
到app.post
的最终处理方式),但我看到了几个红旗检查:
在您的文件和gridFS商店之间设置SaveFile
之后,上面的pipe
函数会立即返回。也就是说,如果您正在移动大文件,并且/或者如果您的MongoDB存储速度相对较慢,那么您在上面提供的代码的调用者很可能会在文件完全复制到MongoDB实例之前获得控制权。链接(例如互联网)。
在这些情况下,很可能在pipe
仍在运行时,调用者会立即进行检查,因此在gridFS存储包含正确的文件副本之前。
另一个问题是,您不会对您创建的流可能生成的事件进行任何错误检查或处理。
修复可能涉及在管道上创建适当的事件处理程序,如下所示:
function SaveFile(file, parameters, response)
{
console.log("Saving");
var stream = grid.createWriteStream(parameters);
pipe = fs.createReadStream(file.path).pipe(stream);
pipe.on('error', function (err) {
console.error('The write of " + file.path + " to gridFS FAILED: ' + err);
// Handle the response to the caller, notifying of the failure
});
pipe.on('finish', function () {
console.log('The write of " + file.path + " to gridFS is complete.');
// Handle the response to the caller, notifying of success
});
}
在传输完成之前,不会调用处理'finish'
事件的函数,因此这是响应app.post
请求的适当位置。如果不出意外,您应该从错误事件中获取有用的信息,以帮助进一步诊断。