Meteor-CollectionFS icon indicating copy to clipboard operation
Meteor-CollectionFS copied to clipboard

Callback when file is uploaded (server-side)

Open zimt28 opened this issue 10 years ago • 7 comments

Hey there! On the server, I need to know when a file has been uploaded, so that its content is available for .createReadStream.

Is there anything like the following? Couldn't find it in the docs.

/* Server */

var file = new FS.File();

file.attachData(url, function(err) {
  Files.insert(file);
});

file.on('stored', function() {
  // File is available for .createReadStream
});

zimt28 avatar Jul 07 '15 08:07 zimt28

Hi,

You indeed have a 'stored' event emitted on the server :

store = new FS.Store.GridFS("storename", {chunkSize: 1024*1024*2});

MyCollection = new FS.Collection('mycollection', {
  stores: [
    store
  ],
});

store.on("stored", function(fileObj, storeName){
  console.log("YO !");
});

The following issue is very instructive on the subject : https://github.com/CollectionFS/Meteor-CollectionFS/issues/351

Hope this helps !

phsultan avatar Jul 07 '15 08:07 phsultan

Hi @phsultan, thanks for your response! It really helps :)

If I get this correctly, I can only notice here that a file has been uploaded, not the file, right? I think I'll just do something like this:

collection.insert(file, function(err, res) {
  store.on('stored', function(storeName, fileObj) {

    // Make sure it's this file
    if (res._id === fileObj._id) {
      // Do something
    }
  });
});

Should work. What do you think?

zimt28 avatar Jul 07 '15 08:07 zimt28

Well, this is how I use it in my case, and I believe this should indeed work. However, maybe you should try fileObj.on("stored", func) as per aldeed's comment in the referenced issue, as it looks a better fit with your case.

This event is mentioned to be available on the server, so I guess it's worth a try for you :)

Cheers !

phsultan avatar Jul 07 '15 09:07 phsultan

Just in case you were not aware of this, another approach is using the observe feature of a cursor. An example would look like: (in CoffeeScript)

cursor = collection.find()
cursor.observe
    added: (doc) ->
        # doc has been just added.
    changed: (doc_new, doc_old) ->
        # doc_old has been just changed to doc_new.
    removed: (doc) ->
        # doc has been just removed.

I find this way quite flexible in my application. Node: Here in the added event handler the file is (most likely) not uploaded yet. A check on isUploaded in the changed event handler would tell when a file is uploaded.

Zodiase avatar Jul 07 '15 14:07 Zodiase

I got this error, if I use a callback function recommended by @phsultan :

/home/kostya/.meteor/packages/cfs_s3/.0.1.3.e4j89r++os+web.browser+web.cordova/npm/node_modules/aws-sdk/lib/request.js:32
          throw err;
                ^
Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.
    at Object.Meteor._nodeCodeMustBeInFiber (packages/meteor/dynamics_nodejs.js:9:1)
    at [object Object]._.extend.get (packages/meteor/dynamics_nodejs.js:21:1)
    at Object.collection.(anonymous function) [as findOne] (packages/matb33_collection-hooks/collection-hooks.js:103:1)
    at [object Object]._.extend.findOne (packages/mongo/collection.js:305:1)
    at [object Object].onImageUploadedCallback (server/collections_server/images.js:64:1)
    at [object Object].emit (events.js:117:20)
    at PassThrough.<anonymous> (packages/cfs_storage-adapter/packages/cfs_storage-adapter.js:210:1)
    at PassThrough.g (events.js:180:16)
    at PassThrough.emit (events.js:117:20)
    at Writable.<anonymous> (packages/cfs_storage-adapter/packages/cfs_storage-adapter.js:419:1)

Kostanos avatar Apr 27 '16 22:04 Kostanos

this is solution for those who have the same issue:

  filestore.on('stored', Meteor.bindEnvironment(onImageUploadedCallback, function(error){
    console.log('Error bindEnvironment', error);
  }));

Kostanos avatar Apr 28 '16 02:04 Kostanos

For anyone reading as of Jan 2018. In the first solution, I found a bug in the callback argument name order:

store = new FS.Store.GridFS("storename", {chunkSize: 1024*1024*2});

MyCollection = new FS.Collection('mycollection', {
  stores: [
    store
  ],
});

// PARAMS ARE BACKWARDS!
store.on("stored", function(fileObj, storeName){
  console.log("YO !");
});

The arguments are reversed in the "stored" callback and should be:

store.on('stored', function(storeName, fileObj) {
    console.log(`storeName: ${storeName}`);
    console.log(`fileObj: ${fileObj}`);
});

cc @phsultan

kyle-rader avatar Jan 21 '18 02:01 kyle-rader