My client code inserts files into images collection similar to this code. Scroll down to see final code altogether. I understand the code makes use of client side hooks (not sure if the same hooks can work server side). How do I make the same code work server side? The code inserts the file into images, fs.chunks and fs.files collections. It works brilliantly client side. But they did not share how to make the same code work server side.
My code looks as follows:
import { FilesCollection } from 'meteor/ostrio:files';
import Grid from 'gridfs-stream';
import fs from 'fs';
let gfs;
if (Meteor.isServer) {
const mongo = MongoInternals.NpmModules.mongodb.module; // eslint-disable-line no-undef
gfs = Grid(Meteor.users.rawDatabase(), mongo);
}
Images = new FilesCollection({
collectionName: 'images',
//allowClientCode: false,
debug: false,
onAfterUpload(image) {
// Move file to GridFS
Object.keys(image.versions).forEach(versionName => {
const metadata = { versionName, imageId: image._id, storedAt: new Date() }; // Optional
const writeStream = gfs.createWriteStream({ filename: image.name, metadata });
fs.createReadStream(image.versions[versionName].path).pipe(writeStream);
writeStream.on('close', Meteor.bindEnvironment(file => {
const property = `versions.${versionName}.meta.gridFsFileId`;
// If we store the ObjectID itself, Meteor (EJSON?) seems to convert it to a
// LocalCollection.ObjectID, which GFS doesn't understand.
this.collection.update(image._id, { $set: { [property]: file._id.toString() } });
this.unlink(this.collection.findOne(image._id), versionName); // Unlink files from FS
}));
});
},
interceptDownload(http, image, versionName) {
// Serve file from GridFS
const _id = (image.versions[versionName].meta || {}).gridFsFileId;
if (_id) {
const readStream = gfs.createReadStream({ _id });
readStream.on('error', err => { throw err; });
readStream.pipe(http.response);
}
return Boolean(_id); // Serve file from either GridFS or FS if it wasn't uploaded yet
},
onAfterRemove(images) {
// Remove corresponding file from GridFS
images.forEach(image => {
Object.keys(image.versions).forEach(versionName => {
const _id = (image.versions[versionName].meta || {}).gridFsFileId;
if (_id) gfs.remove({ _id }, err => { if (err) throw err; });
});
});
},
});
if (Meteor.isServer) {
Images.denyClient();
}
Example of inserting a file client side is
'change .persInfoFileInput': function (e, template) {
var username = this.username;
var user = Meteor.users.findOne({username: username});
var id;
var fileName;
id = user._id;
//event.preventDefault();
if (e.currentTarget.files && e.currentTarget.files[0]) {
// We upload only one file, in case
// there was multiple files selected
var file = e.currentTarget.files[0];
var fileName = "User_" + id + "_" + "Details" + "_"
Images.insert({
file: file,
fileName: fileName + e.currentTarget.files[0].name,
onStart: function () {
template.currentUpload.set(this);
},
onUploaded: function (error, fileObj) {
if (error) {
alert('Error during upload: ' + error);
} else {
}
template.currentUpload.set(false);
},
streams: 'dynamic',
chunkSize: 'dynamic'
});
}
},
Example of deleting file client side is:
"click .deletePersInfoFile": function (event) {
var id = event.target.name;
Images.findOne(id).remove();
}
Displaying the file looks something like this
persInfoImages: function () {
var username = this.username;
var user = Meteor.users.findOne({username: username});
var id;
var partOfFileName;
id = user._id;
partOfFileName = ".*User_" + id + "_" + "Details_.*";
//search = new RegExp(partOfFileName, 'i');
//var imgs = Images.find({"name":search});
var imgs = Images.find({"name":{$regex:partOfFileName}});
//var imgs = Images.find({"copies.images.name":{$regex:partOfFileName}})
//var imgs = Images.find();
return imgs // Where Images is an FS.Collection instance
}
Ofcourse the above are the invoked methods for inserting, removing and dispaying. I omitted the html side of things.