如何在 jQuery File Upload 中上传所有文件时在服务器端使用 stop 事件



我在express上使用jQuery File Upload.js使用jquery-file-upload-middleware,使用mongoDB使用mongoose。

我想上传画廊的图片。Galery 对象包含图像对象的数组,例如

var GalerySchema = new mongoose.Schema({
    images: [ImageSchema]
})

异步上传每个文件后,我想将其推送到 Galery 对象的图像数组中。

我尝试执行以下服务器端操作:

// Is called everytime an image is uploaded
upload.on('end', function(fileInfo, rew, res){
    // Get the galery
    db.Galery.findOne({_id: req.fields.galery_id}, function(err, galery){
        // Create new Image object instance
        var image = new db.Image({src: fileInfo.name});
        // Save, in order to create auto generated _id
        image.save(function(err){
            if(err) {console.log(err); return; }
            // Add to Images array of Galery object
            galery.images.push(image);
            // Save galery with added image
            galery.save(function(err){
                if(err) { console.log(err); return; }
            });
        })
    });
});

这样做,我得到了一个众所周知的[VersionError: No matching document found.],据我目前所知,这是由于同时访问同一个mongodb文档,因为上传是异步发生的。

因此,为了处理问题的异步方式,最好等待所有上传完成,然后将图像一个接一个地插入mongodb,即使用async.parallel()

但是,如何访问所有上传已完成的事件?

我知道浏览器端我可以使用停止事件。但首先,这不包含有关上传文件的任何数据。另外,我想在服务器端执行此操作。

有没有类似的东西

upload.on('doneAll', function(allFilesInfo, req, res){...})?
你可以

使用承诺(Bluebird:https://github.com/petkaantonov/bluebird,npm install bluebird --save)并得到这样的东西:

var BPromise = require('bluebird');
var uploadDone = new BPromise(function (resolve, reject) {
    // your image upload
});
uploadDone.then(function (result) {
   // upload complete here
}, function (error) {
   console.log("Error: ", error);
});

由于 jQuery File Upload 为每个文件创建一个 XHR,因此它们在服务器端被视为单独的 POST,上传中间件没有直接的方法知道所有上传何时完成。您可以创建另一个端点作为停止事件的回调,但正如您已经知道的那样,这不仅缺少有关上传内容的信息,而且如果两个或多个用户碰巧同时上传,也不会有太大帮助。

我相信您需要的是使用 findOneAndUpdate (或 findByIdAndUpdate) 调用来对Galery执行更新。有关如何$push imagegalery的示例,请参阅此答案。

上传时,您将对每个文件向服务器执行一个请求,或者如果您使用的是sequentialUploads: true,则总共执行一个请求。如果想知道在异步场景中上传所有图像的时间,则需要使用 express 定义一个额外的路由,并在所有文件完成后向调用此路由的文件上传器添加回调。然后,您还需要跟踪之前上传了哪些文件并且未保存。如果您的脚本由多个人使用(公共访问?),那么您还需要实现一些会话处理,以保存调用"uploadDone"路由时要添加的上传文件。如您所见,这是很大的开销,因此我建议使用sequentialUploads: true解决方案。

但是,我几乎不相信您会因为同时访问图库文档而获得[VersionError: No matching document found.],因为获取/保存文档只需几毫秒。我建议您检查req.fields.galery_id是否已发送。

console.log(req.fields.galery_id);

最新更新