Looking for very simple file upload example?

There is a lot of stuff out there, for file uploads, but I just need the simple use case of letting the user browse to a file, click “upload” and then be able to process it on the server… I want to store it on my local server

I have a simple example working by doing:

common.js

YourFileCollection = new FS.Collection("yourFileCollection", {
    stores: [new FS.Store.FileSystem("yourFileCollection", {path: "~/meteor_uploads"})]
});
YourFileCollection.allow({
    insert: function (userId, doc) {
        return true;
    },
    update: function (userId, doc) {
        return true;
    },
    remove: function (userId, doc) {
        return true;
    },
    download: function (userId, doc) {
        return true;
    }
});

template:

<input class="your-upload-class" type="file">

  <table class="table table-condensed">
        <tbody>
        {{#each theFiles}}
        <tr>
    <td>{{uploadedAt}}</td><td>{{original.name}}</td><td><a
 href="{{url}}">link</a></td><td>{{#if 
isUploaded}}uploaded{{/if}}</td><td><button 
id="deleteFileButton">delete</button></td>
        </tr>
        {{/each}}
        </tbody>
      </table>

server:

Meteor.publish("fileUploads", function () {
  console.log("publishing fileUploads");
  return YourFileCollection.find();
});

client

Meteor.subscribe("fileUploads");
    Template.home.events({
      'click #deleteFileButton ': function (event) {
        console.log("deleteFile button ", this);
        YourFileCollection.remove({_id:this._id});
        
      },
      'change .your-upload-class': function (event, template) {
    console.log("uploading...")
    FS.Utility.eachFile(event, function (file) {
      console.log("each file...");
      var yourFile = new FS.File(file);
      yourFile.creatorId = 123; // todo
      YourFileCollection.insert(yourFile, function (err, fileObj) {
        console.log("callback for the insert, err: ", err);
        if (!err) {
          console.log("inserted without error");
        }
        else {
          console.log("there was an error", err);
        }
      });
    });
  }
});

Template.home.helpers({
  theFiles: function () {
    return YourFileCollection.find();
  }
});

So, hopefully this will help someone… and now I need some help… I’ve implemented my own login/logout functionality, just by setting a session variable… so, how can I protect my downloads so they cannot be accessed when the user is not logged in? I’m not familiar with how the allow/deny works, as you can see I have just returned true from all of them to get things working for now…

Also, it may be obvious to some, but I was confused for a while as to how I could delete my uploads… I decided to just try a .remove on my collection and it worked… that’s cool, but where is this explained in the documentation? I might be missing a good example or source of documentation on this topic.

Thanks.

3 Likes

Hi,
thanks for your example, but i’m unable to upload the file.
When i choose the file, nothing happen.
Thanks a lot.

are you seeing the “uploading…” message in your browser console? That should be displayed once you choose a file to upload, as it should execute based on the change event on the .your-upload-class element on the browser… let me know if you see that message

Thanks for reply, no uploading message in console…
I20150501-21:43:28.379(0)? publishing fileUploads

Sorry I don’t know then… if your input element of type file has that class declaration, it should fire the event … try a different browser… If I have time I will try to put this together in a github or meteorpad

Thanks a lot,
if you can put it on github are great. I don’t know why doesn’t work. Thanks a lot!

Here it is, hope it helps!

1 Like

You should be able to compare the Meteor user with the document user within the download function in your common.js.
Something like…

download: function (userId, doc) {
return Meteor.userId === doc.userId;
}

Yes, but that only works if I’m using the built in meteor login system, and as of last week, I was not using it, because I needed my own custom login functionality that posted to an external web service to check credentials. Therefore I wrote my own system that just relied on setting a session variable to indicate the user was logged in or not. I have since integrated with the Meteor login system via Accounts.registerLoginHandler, so now the userId is properly set in the download checking function. so all is well!

Hello ! I tried your code but I have this error :

Your app is crashing. Here's the latest log. ReferenceError: FS is not defined

Do you have any idea how can I define “FS” ? Thank you a lot !

Did you include the packages cfs:filesystem and cfs:standard-packages?

I have put a simple example in my book, you can see the code on GitHub. The solution is only very simple and uses the MongoDB to store files and on the client side relies on the HTML5 File API.

@klim the necessary packages should get included as they are in the .meteor folder:

So, I’m not sure why this error would happen.

@yauh Thanks for that example, I’ll take a look!

You’re right, I will do this. Thank you !

Is there disadvantages in using MongoDB to store files? just a dummy question

@ralpheiligan in my situation, I’m migrating from an older system that stored files on the filesystem, so I need to keep that scheme.

@wesyah234 I understand however I would like to know if there’s an advantages using your scheme or using mongodb? The reason I ask because my application will start using file uploads.

Well, in general, and this is not specific to the mongo/meteor platform, the advantage of storing on the filesystem is that it is easier to move to a different environment some day. If you had stored your files in a blob in a database, and wanted to move to a different database, it would be more work to migrate.

I am updating this thread because I have now evaluated another Meteor file upload/download library: https://github.com/tomitrescak/meteor-uploads

It is pretty good in the sense that it uses the JQuery file upload system, plus you have more control over the collection you use on your mongo db for storing the metadata. Overall, I like those parts of it, however, it is not so great when it comes to controlling access to the files for making download links… ie. if you have a link to download a file, and that link gets into the wild, you would hope it wouldn’t work after the user is logged out, or their session has expired… but it does still work, forever, unless you implement something special. IN contrast, https://github.com/CollectionFS/Meteor-CollectionFS gives you allow/deny placeholders where you have access to Meteor.accounts so you can easily check if the user is still logged in.

Anyway, I put together a simple demo (not using login/logout though)… I tried to keep it as much like the collection fs example as possible for comparison.

1 Like

@ralpheiligan
Hey, I just found this SO post:


that is a good comparison… see option 1 for some Cons of storing in mongodb… not sure if all of these are still valid though…

1 Like