0

我正在使用此代码进行文件更新:

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 替换文件的正确方法是什么?

4

1 回答 1

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请求的适当位置。如果不出意外,您应该从错误事件中获得有用的信息,以帮助进一步诊断。

于 2013-12-09T01:02:23.833 回答