如何用gridfs-stream替换?

时间:2013-06-17 03:51:43

标签: gridfs gridfs-stream

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

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

1 个答案:

答案 0 :(得分:0)

很难从你提供的代码中确切地说出来(即你没有展示responseapp.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请求的适当位置。如果不出意外,您应该从错误事件中获取有用的信息,以帮助进一步诊断。