Skip to content
This repository has been archived by the owner on Mar 14, 2019. It is now read-only.

Getting Started

GiraffeSlacks edited this page Mar 29, 2015 · 3 revisions

Before you start… One of the best ways to learn how CollectionFS works is to enable debug mode. Set FS.debug = true in a location that loads early to see additional logging.

The first step in using this package is to define a FS.Collection.

common.js:

Images = new FS.Collection("images", {
  stores: [new FS.Store.FileSystem("images", {path: "~/uploads"})]
});

In this example, we've defined a FS.Collection named "images", which will be a new collection in your MongoDB database with the name "cfs.images.filerecord". We've also told it to store the files in ~/uploads on the local filesystem. If you don't specify a path, a cfs/files folder in your app container (bundle directory) will be used.

Your FS.Collection and FS.Store variables do not necessarily have to be global on the client or the server, but be sure to give them the same name (the first argument in each constructor) on both the client and the server.

If you're using a storage adapter that requires sensitive information such as access keys, we recommend supplying that information using environment variables. If you instead decide to pass options to the storage adapter constructor, then be sure that you do that only in the server code (and not simply within a Meteor.isServer block).

Now we can upload a file from the client. Here is an example of doing so from the change event handler of an HTML file input:

Template.myForm.events({
  'change .myFileInput': function(event, template) {
    var files = event.target.files;
    for (var i = 0, ln = files.length; i < ln; i++) {
      Images.insert(files[i], function (err, fileObj) {
        //Inserted new doc with ID fileObj._id, and kicked off the data upload using HTTP
      });
    }
  }
});

You can optionally make this code a bit cleaner by using a provided utility method, FS.Utility.eachFile:

Template.myForm.events({
  'change .myFileInput': function(event, template) {
    FS.Utility.eachFile(event, function(file) {
      Images.insert(file, function (err, fileObj) {
        //Inserted new doc with ID fileObj._id, and kicked off the data upload using HTTP
      });
    });
  }
});

Notice that the only thing we're doing is passing the browser-provided File object to Images.insert(). This will create a FS.File from the File, link it with the Images FS.Collection, and then immediately begin uploading the data to the server with reactive progress updates.

The insert method can directly accept a variety of different file representations as its first argument:

  • File object (client only)
  • Blob object (client only)
  • Uint8Array
  • ArrayBuffer
  • Buffer (server only)
  • A full URL that begins with "http:" or "https:"
  • A local filepath (server only)
  • A data URI string

Where possible, streams are used, so in general you should avoid using any of the buffer/binary options unless you have no choice, perhaps because you are generating small files in memory.

The most common usage is to pass a File object on the client or a URL on either the client or the server. Note that when you pass a URL on the client, the actual data download from that URL happens on the server, so you don't need to worry about CORS. In fact, we recommend doing all inserts on the client (managing security through allow/deny), unless you are generating the data on the server.