我正在使用以下代码进行文件更新:
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替换文件的正确方法是什么?
发布于 2013-12-09 09:02:24
仅从您提供的代码中很难确定(即,您没有展示app.post的response最终是如何处理的),但我看到了几个需要检查的危险信号:
在您的文件和gridFS存储之间设置pipe后,上面的SaveFile函数将立即返回。也就是说,如果您正在移动大文件,和/或如果您的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请求的适当位置。如果没有其他问题,您应该从错误事件中获得有用的信息,以帮助进一步诊断此问题。
https://stackoverflow.com/questions/17140172
复制相似问题