Meteor-files: Specify a relative subfolder on individual uploads

Created on 20 Dec 2016  路  16Comments  路  Source: veliovgroup/Meteor-Files

Yes, I have seen #99 and #190.
But let me rephrase our problem... (which is similar to the above).

We want to store files as kind of attachments to JSON documents we store in MongoDB (in our case meeting minutes grouped by meeting series, see https://github.com/4minitz/4minitz). We use Meteor-Files and really like the feature set (Big thanks, man for all the work!!!) and good demo documentation.

But we are a bit concerned that over the years quite some thousand attachments will populate the one-and-only global upload directory (aka storagePath) that is attached to the FilesCollection (e.g. the file system might get slow, everything in one big messy dir, etc.).

We have the FileCollection storagePath. Now we would like all uploads to meetingseries XYZ to go into /global/storage/path/XYZ and all uploads for meeting series ABC go into /global/storage/path/ABC

Is this possible - and if yes: how?!
If no: What about an option for FileCollection.insert({relativeSubFolder: "XYZ"})

Thanks for any helpful hint.

Most helpful comment

Hey! Wow!
That sounds really promising. Thanks f眉r the lightning-fast answer!
I was not aware that storagePath is a function.
Thanks - I'll give it a try and report.

All 16 comments

Hi @derwok

I'm glad you found my work useful, thank you.

storagePath is a function, you're free to return any path.
Here is an example how to generate deep path from _id:

const fs = Npm.require('fs-extra');
const files = new FilesCollection({
  storagePath: function (fileObj) {
    // Do not use "fat arrow" as context is matters
    if (fileObj && fileObj._id) {
      let path = 'assets/app/uploads/defaultPath/' + fileObj._id.split('').join('/');
      fs.ensureDirSync(path);
      return path;
    } else {
      return 'assets/app/uploads/defaultPath';
    }
  }
});

Hey! Wow!
That sounds really promising. Thanks f眉r the lightning-fast answer!
I was not aware that storagePath is a function.
Thanks - I'll give it a try and report.

Your code did the trick.
fs.ensureDirSync was also a great idea!

I only had to do a npm install --save fs-extra and in my code:

let fs;
if (Meteor.isServer) {
    fs = require('fs-extra');   // throws an error on client
}

Thanks again for premium-class support and a great package!

@derwok great, I'm glad it's solved.

@dr.dimitru, extremely useful staff!
I urge all donate him!
thanks to its function, I made splitting folders by names of first's "_id" symbols:

 storagePath: function(fileObj) {
      let fs = require('fs-extra');
      if (Meteor.isServer) {
         if (fileObj && fileObj._id) {
      let path = Meteor.settings.public.IMG_PATH + fileObj._id.substr(0,3);
      fs.ensureDirSync(path);
      return path;
      } else {
      return Meteor.settings.public.IMG_PATH;
        }
    }
  }

Thank you, @valorloff

About this line: let fs = require('fs-extra');
With efficiency in mind - better to place require out of the functions (more here and here).
It's best practice is to place all require/import out of the function and conditional blocks.

I urge all donate him!

Star/like any of my projects is highly appreciated too.

Yes, of course! Thanks for this point

recently some android browsers crash with
'Uncaught SyntaxError: Use of const in strict mode'
perhaps because of require('fs-extra'), that contain 'use strict' with 'const ....'
and declared in /lib/collections.js:

const fs = require('fs-extra');
Images = new FilesCollection({
  collectionName: 'Images',
  allowClientCode: false, 
  storagePath: function(fileObj) {
      if (Meteor.isServer) {
          if (fileObj && fileObj._id) {
      const path = Meteor.settings.private.IMG_PATH + fileObj._id.substr(0,3);
      fs.ensureDirSync(path);
      return path;
      } else {
      return Meteor.settings.private.IMG_PATH;
        }
    }
  },

It means, fs-extra by some way gets to the client?
How i can isolate storagePath with fs from client?

@valorloff

recently some android browsers crash with
'Uncaught SyntaxError: Use of const in strict mode'

Looks like related to #445 and probably #444

How i can isolate storagePath with fs from client?

Initiate FilesCollection separately for Server and Client, see "Locus" column here

yes, looks like it,
If fs placed in a Meteor.isServer block, this is not a separation?
so, wait for upgrade?

If fs placed in a Meteor.isServer block, this is not a separation?

No, library will be anyways preloaded.

after separate pathStorage to server:

Uncaught SyntaxError: Use of const in strict mode.ostrio_files.js?hash=84ab9a263f25925de581338ed9648d3c07c66024:4419

expand it:

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                     //
// node_modules/meteor/ostrio_files/node_modules/fs-extra/lib/index.js                                                 //
//                                                                                                                     //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                                                                                       //
'use strict'                                                                                                           // 1
                                                                                                                       // 2
const assign = require('./util/assign')                                                                                // 3
                                                                                                                       // 4
const fs = {} 
............  

Uncaught SyntaxError: Use of const in strict mode.ostrio_files.js?hash=84ab9a263f25925de581338ed9648d3c07c66024:4419

Is this on the Client?

This is errors, generated by Android default browsers,
look this screen shot
g1

This is errors, generated by Android default browsers,

It's definitely #445

What you can do now for quick fix is fork this package, and locally set fs-extra to v2.1.2

thanks for excellent support!
no problems, I'll wait upgrade

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ck23onGithub picture ck23onGithub  路  3Comments

owenhoskins picture owenhoskins  路  3Comments

tuarrep picture tuarrep  路  4Comments

RE-N-Y picture RE-N-Y  路  3Comments

msgfxeg picture msgfxeg  路  3Comments