What would be the canonical way to handle a file upload with Meteor?
-
2That's a vague question... Are you asking how to handle it on the client side, or the server? Either way, I imagine (I've never used meteor) that the way to handle a file upload is pretty much the same as with any server. Client side: send POST request to a URL with the file as part of the request body. Server side: listen for POST requests at that URL, and when one comes in, read the request body and do whatever you want with any files it contains. That's basically how I've done it with node/spring... If you can be more specific about what you need help with, perhaps I can be more helpful... – JKing Apr 11 '12 at 03:25
-
29Hi JKing, you should check out Meteor, that's why it's an interesting question: http://meteor.com/ – David Apr 11 '12 at 13:28
12 Answers
I used http://filepicker.io. They'll upload the file, store it into your S3, and return you a URL where the file is. Then I just plop the url into a DB.
Wget the filepicker script into your client folder.
wget https://api.filepicker.io/v0/filepicker.js
Insert a filepicker input tag
<input type="filepicker" id="attachment">
In the startup, initialize it:
Meteor.startup( function() { filepicker.setKey("YOUR FILEPICKER API KEY"); filepicker.constructWidget(document.getElementById('attachment')); });
Attach a event handler
Templates.template.events({ 'change #attachment': function(evt){ console.log(evt.files); } });

- 668
- 1
- 5
- 6
-
-
-
8
-
-
6Echo @rijk, don't know why a paid service is #1 voted answer.. https://github.com/VeliovGroup/Meteor-Files or https://themeteorchef.com/recipes/uploading-files-to-amazon-s3/ are both free solution implementing open source libs. – GFargo Dec 22 '15 at 15:51
-
1I use `edgee:slingshot`, it's great for large files (uploads directly to S3, not via your app server). – Rijk Dec 23 '15 at 14:10
For images, I use a method similar to Dario's except I don't write the file to disk. I store the data directly in the database as a field on the model. This works for me because I only need to support browsers that support the HTML5 File API. And I only need simple image support.
Template.myForm.events({
'submit form': function(e, template) {
e.preventDefault();
var file = template.find('input type=["file"]').files[0];
var reader = new FileReader();
reader.onload = function(e) {
// Add it to your model
model.update(id, { $set: { src: e.target.result }});
// Update an image on the page with the data
$(template.find('img')).attr('src', e.target.result);
}
reader.readAsDataURL(file);
}
});

- 1
- 1

- 1,920
- 1
- 25
- 25
I've just come up with an implementation of file uploads using Meteor.methods and HTML5 File's API. Let me know what you think.

- 19,824
- 17
- 99
- 186

- 1,692
- 13
- 9
-
3So, those instructions worked surprisingly well. The solution was 10x easier than I expected, and the code pretty much worked flawlessly. That being said, the solution uploads the images directly to the node.js local file system. It worked great at first on local dev machines, but had problems with platform-as-a-service (PaaS) providers, including Heroku and Nodjitsu. Problem being that there are filesystem permission issues with this solution. So, this solution requires either hosting your own server, or having a more robust infrastructure, such as Amazon Elasticbeanstalk. – AbigailW Dec 25 '12 at 05:32
There currently doesn't seem to be a way to interact with the HTTP server or do anything related to HTTP.
The only things you can do is talk to server over the RPC methods exposed by Meteor.methods or talk to mongoDB directly over the mongoDB API exposed.

- 166,823
- 56
- 351
- 396
-
Thanks Raynos. Will probably try Luan's way and bypass the upload with JS uploaders to S3 or something of the sort. – David Apr 11 '12 at 13:29
-
1@Raynos Do you know if the exposed Mongo API supports GridFS? I can't see mention of it. – Steve Jalim Apr 12 '12 at 09:32
-
@stevejalim I dont know, go read the source code for the subset of the mongo API it supports – Raynos Apr 12 '12 at 13:47
-
1@stevejalim I looked at the source there isn't any GridFS support in minimongo (the package they use) – bobbywilson0 Apr 14 '12 at 03:15
-
-
The answer is now overtaken by events (Meteor moves fast); HTTP is available, see docs http://docs.meteor.com/#meteor_http – CSSian Apr 22 '12 at 18:54
-
-
@Raynos - Ah, right you are; I know better to trust headlines on announcements :( – CSSian Apr 24 '12 at 18:28
-
3I'm a little late to the party here, but you can also check out the last few episodes of eventedmind.com where I'm building a file uploader for meteor. The streaming upload version of the package will be released this week. It's called meteor-file. – cmather May 15 '13 at 01:48
-
Hey Raynos, this answer is not obsolete (Meteor has moved very fast since 2012). Any chance to update or delete it? Thanks. – Dan Dascalescu Dec 15 '14 at 08:39
There is a new package: edgee:slingshot. It does not upload the files to your meteor server, but it is better that way as it allows the meteor server to focus on its primary objective of serving the meteor app instead of handling costly file transfers.
Instead it uploads files to cloud storage services. Currently it supports AWS S3 and Google Cloud Files, but it will also support Rackspace Cloud Files and perhaps Cloudinary in the future.
Your meteor server merely acts as as a coordinator.
It is also a very versatile and light-weight package.

- 4,381
- 2
- 29
- 48
there is an atmosphere package called router which allows just that.
actually, the best way to handle file uploads is now collectionFS

- 3,957
- 2
- 30
- 48
-
1CFS group of addons are not suitable for production - because of them our Meteor app deployment failed continuously, especially after upgrading the app to Meteor 1.0. I strongly recommend against using CFS packages. – Gelmir Nov 05 '14 at 09:00
Here is the best solution for this time. It uses collectionFS.
meteor add cfs:standard-packages
meteor add cfs:filesystem
Client:
Template.yourTemplate.events({
'change .your-upload-class': function(event, template) {
FS.Utility.eachFile(event, function(file) {
var yourFile = new FS.File(file);
yourFile.creatorId = Meteor.userId(); // add custom data
YourFileCollection.insert(yourFile, function (err, fileObj) {
if (!err) {
// do callback stuff
}
});
});
}
});
Server:
YourFileCollection = new FS.Collection("yourFileCollection", {
stores: [new FS.Store.FileSystem("yourFileCollection", {path: "~/meteor_uploads"})]
});
YourFileCollection.allow({
insert: function (userId, doc) {
return !!userId;
},
update: function (userId, doc) {
return doc.creatorId == userId
},
download: function (userId, doc) {
return doc.creatorId == userId
}
});
Template:
<template name="yourTemplate">
<input class="your-upload-class" type="file">
</template>

- 7,508
- 4
- 27
- 25
-
I use all your code. Meteor starts normal but after i clicked an item it doesn't upload it to the server? Nothing happends. – Erdem Güngör Dec 07 '14 at 12:56
-
@ErdemGüngör Check that **yourTemplate** and **your-upload-class** in html are the same as Template. **yourTemplate** .events and 'change **.your-upload-class**'. The to add console.log at event handler function. – Raz Dec 09 '14 at 13:43
-
@Raz Would you recommend using them? Their devel branch (which seems to be the default on Github) says - "This branch is under active development right now (2015-01-26). It has bugs and the API may continue to change. Please help test it and fix bugs, but don't use in production yet." And their Master branch seems pretty old. I am thinking of taking the risk. What do you suggest? – Ayrton Senna Feb 19 '15 at 09:15
-
1@AyrtonSenna We use it in production on the small project and it works well. But you should do nice regression tests after each `meteor update`. Not only because of this package. – Raz Feb 24 '15 at 16:53
-
collectionFS is now deprecated, so this is not anymore a solution. Anyway, I implemented a solution with it and had to handle with many bugs which in the end made me change totally to other option: Uploadcare. – Menda Jun 03 '16 at 09:35
-
CollectionFS is deprecated, but it still works, and especially so with GridFS for those that don't want to store files directly on the server disk. – Joel Trauger Jun 10 '16 at 21:19
-
@JoelTrauger I have some problems with CollectionFS in Galaxy environment. No problems in localhost. I'll try another plugin. – iiro Jun 14 '16 at 06:53
If you do not require significantly large files or maybe only storing the files for a short period of time then this simple solution works very well.
In your html...
<input id="files" type="file" />
In your template event map...
Template.template.events({
'submit': function(event, template){
event.preventDefault();
if (window.File && window.FileReader && window.FileList && window.Blob) {
_.each(template.find('#files').files, function(file) {
if(file.size > 1){
var reader = new FileReader();
reader.onload = function(e) {
Collection.insert({
name: file.name,
type: file.type,
dataUrl: reader.result
});
}
reader.readAsDataURL(file);
}
});
}
}
});
Subscribe to the Collection and in a template render a link...
<a href="{{dataUrl}}" target="_blank">{{name}}</a>
While this might not be the most robust or elegant solution for large files or a file intensive application it works very well for all kind of file formats if you want to implement simple upload and download/rendering of the files.

- 3,682
- 3
- 36
- 49
You could try uploading directly to amazon S3, doing some tricks with js uploaders and stuff. http://aws.amazon.com/articles/1434

- 402
- 3
- 6
-
There are [packages that handle S3 uploads for Meteor](https://atmospherejs.com/?q=s3) now. – Dan Dascalescu Dec 15 '14 at 08:40
You can see on the meteor roadmap that the feature "File upload pattern" is scheduled for "After 1.0". So we have to wait to see an official way.
For now, one of the best ways is to use "collectionFS" (which is 0.3.x dev preview at the time of writting).
Or inkfilepicker (ex. filepicker.io) as suggested here. It is easy enough to use, although this obviously requires and Internet connection from the user side.
If it just to play around, you could as well take advantage of the html5 feature. Something like that.

- 17,623
- 13
- 87
- 133
-
collectionFS is very powerful and for right now it seems like the best way to go. – benathon Jul 01 '14 at 08:11
To accomplish the same action as the most upvoted answer without the cost of filepicker.io, follow the instructions for this package: https://github.com/Lepozepo/S3
Then to obtain the link, use code similar to below. Finally, plug the url returned by secureLink into the DB.
Template.YourTemplate.events({
"click button.upload": function() {
var files = $("input.file_bag")[0].files;
S3.upload(files, "/subfolder", function(e,r) {
console.log(r);
Session.set('secureLink', r.secure_url);
})
}
});
Template.YourTemplate.helpers({
"files": function() {
return S3.collection.find();
},
"secureLink": function() {
return Session.get('secureLink');
}
});
-
Thanks for the `$("input.file_bag")[0].files`. I was struggling to find a way to get the returned data from a file type input. – Adriano P May 24 '16 at 22:11
here is yet another solution:
https://doctorllama.wordpress.com/2014/11/06/meteor-upload-package-with-jquery-file-upload/
This one is using Blueimp's upload solution that supports chunked uploads, progress bars and more.

- 1,072
- 12
- 22