Rolled my own. But in case anyone else is looking for how to upload files in Meteor 1.3:
<input type="file" onChange={beginFileUpload} />
This of course means that file upload will begin immediately after selecting a file. Setting multiple
is perfectly fine as well so you can upload more than one file simultaneously.
beginFileUpload: (e) => {
if(Roles.userIsInRole(Meteor.user()._id, 'admin', 'admin_group')) {
let input = e.target;
_.each(input.files, function(file) {
let fileReader = new FileReader();
let encoding = "binary";
let name = file.name;
fileReader.onload = function() {
if(fileReader.readAsBinaryString) {
Meteor.call('saveFile', fileReader.result, name, '', encoding);
} else {
var binary = "";
var bytes = new Uint8Array(fileReader.result);
var length = bytes.byteLength;
for(var i=0; i < length; i++) {
binary += String.fromCharCode(bytes[i]);
}
Meteor.call('saveFile', binary, name, '', encoding);
}
};
fileReader.onloadend = function (e) {
console.log(e);
};
fileReader.onloadstart = function (e) {
console.log(e);
};
fileReader.onprogress = function (e) {
console.log(e);
};
fileReader.onabort = function (e) {
console.log(e);
};
fileReader.onerror = function (e) {
console.log(e);
};
if(fileReader.readAsBinaryString) {
fileReader.readAsBinaryString(file);
} else {
fileReader.readAsArrayBuffer(file);
}
});
}
}
Take note of the final if-clause and the one inside the onload event handler - that one is needed to deal with the Internet Explorer as it does not know the readAsBinaryString method. You can use the copious other event handlers to deal with displaying info about the upload.
Finally:
const fs = require('fs');
Meteor.methods({
saveFile: function(blob, name, path, encoding) {
if(Roles.userIsInRole(Meteor.user()._id, 'admin', 'admin_group')) {
console.log("Allowed");
if(process.env.NODE_ENV === "production") {
var path = '/var/www/static';
} else {
var path = process.env['METEOR_SHELL_DIR'] + '/../../../public/static';
}
var filename = name.toLowerCase().replace(/ /g,'_').replace(/ä/g,'ae').replace(/ö/g,'oe').replace(/ü/g,'ue').replace(/ß/g,'ss').replace(/[^a-z0-9_.]/g,'');
fs.writeFile(path+"/"+filename, blob, encoding, Meteor.bindEnvironment(function(err){
if(err) {
console.log("Error:"+err);
} else {
console.log("Success");
FileCollection.insert({name: name, filename: filename});
}
}));
}
}
});
Here you’ll note three things, basically. Firstly, I’m using alanning:roles
to make sure that actually saving files is only doable by worthy persons.
Secondly, I’m sending my files somewhere else in production than I’m doing in development (the huge mess of strings is due to how finding the directory under Windows works) - the URI is the same for both, because I configured the nginx webserver to serve up anything under /static
directly and not through the Node process.
Thirdly, I’m sanitizing my filename a bit, replacing spaces with underscores, Umlaute with similar ASCII counterparts and finally stripping away anything else. This method only lives on the server, so it’s not optimistic.