aheckmann / gridfs-stream

Easily stream files to and from MongoDB
MIT License
615 stars 120 forks source link

Uploading multiple files with gridfs to mondo db on meteor throws error #120

Open koblents opened 6 years ago

koblents commented 6 years ago

Hi!

We have an meteor application with screen for multiple images upload. Recently we switched from file system storage to mongo db. For this we are using gridfs-stream with ostrio:files and here is exception we are catching during upload (after exception meteor app is crashing)

`[FilesCollection] [findOne({"_id":"9hsh7WsT55ufs9czs"}, undefined)] [FilesCollection] [findOne({"_id":"gz49qGqY7Q7by5aHE"}, undefined)] [FilesCollection] [findOne({"_id":"ioLE37TXw47KDgLuy"}, undefined)]

[FilesCollection] [Upload] [finish(ed)Upload] -> /hdb/home/subbotnik/pictures/MrrK5ZerAkNFD4PAz.jpg [FilesCollection] [Upload] [HTTP] Got #-1/3 chunks, dst: 17772.jpg [FilesCollection] [Upload] [finish(ing)Upload] -> /hdb/home/subbotnik/pictures/zSBgJa2xcMPsaNMFt.jpg [FilesCollection] [Upload] [HTTP] Got #-1/3 chunks, dst: 12215.jpg [FilesCollection] [Upload] [finish(ing)Upload] -> /hdb/home/subbotnik/pictures/RL9nzRKB92PZSyJxu.jpg [FilesCollection] [Upload] [finish(ed)Upload] -> /hdb/home/subbotnik/pictures/zSBgJa2xcMPsaNMFt.jpg [FilesCollection] [findOne({"_id":"6ZjAS3jvgNtsRG4AG"}, undefined)]

events.js:141 throw er; // Unhandled 'error' event ^

Error: ENOENT: no such file or directory, open '/hdb/home/subbotnik/pictures/ioLE37TXw47KDgLuy.jpg' `

our meteor version is 1.5 ostrio:files version is 1.7.17 and gridfs-stream version is 1.1.1

Here is our code which write images to Gridfs

`var writeStream = gfs.createWriteStream({
                            filename: file.name,
                            metadata: metadata,
                            mode: 'w',
                            content_type: content_type
                        });
                        if (writeStream) {
                            fs.createReadStream(file.versions[metadata.versionName].path).pipe(writeStream);
                            writeStream.on('close', Meteor.bindEnvironment(function (filegrid) {
                                // If we store the ObjectID itself, Meteor (EJSON?) seems to convert it to a
                                // LocalCollection.ObjectID, which GFS doesn't understand.
                                var $set = {};
                                var idString = filegrid._id.toString();

                                var extension = '.' + Mime.extension(filegrid.contentType);
                                try {
                                    Gridfiles.update({_id: new Mongo.ObjectID(idString)}, {
                                        $set: {
                                            filename: filegrid.md5,
                                            extension: extension
                                        }
                                    });
                                    $set['versions.' + metadata.versionName + '.gridFsFileId'] = idString;

                                    Media.update(filegrid.metadata.imageId, {
                                        $set: $set
                                    });
                                     fs.unlink(file.versions[metadata.versionName].path, function (err) {
                                         if (err) {
                                             console.log(err);
                                         }
                                     });
                                } catch (err) {
                                    console.log(err);
                                }
                            }));`

and for read images


'interceptDownload(http, image, versionName) {
        if (Meteor.settings.public.files == "gridfs") {
            // Serve file from GridFS
            const _id = (image.versions[versionName] || {}).gridFsFileId;
            if (_id) {
                var readStream = gfs.createReadStream({_id});
                if (readStream) {
                    readStream.pipe(http.response);
                    readStream.on("error", function (err) {
                        console.log(err);
                        return false;
                    });
                } else {
                    console.log(error);
                }
            } else {
                console.log(image._id + " has no gridfs link");
            }
            return true;
            // return Boolean(_id); // Serve file from either GridFS or FS if it wasn't uploaded yet
        } else {
            return false;
        }
    },'

So, generaly we

  1. upload images to our server ( storagePath: '/pictures') 1.1 here we also create to more images (thumb and original in .png format with Imagemagick.convert)
  2. write those images to gridfs
  3. delete images from file system.

I can't really catch error that we got into log and I don't understand why it occurs. It looks that some files first deleted with removeUnfinishedUpload and then we are trying to get it..

Please suggest. Thank you.

P.S. error happens not each time, but time to time