I am using CollectionFS for image management. In addition, I use graphicsmagick gm() for image management.
Now I want to crop the already saved image. Therefore, when the click event is called, the server method that executes crop () is called. But after that in the collection I find an empty image with size=0 updated on the correct date.
I do not see what I am doing wrong.
shared.js
Images = new FS.Collection("images", { stores: [ new FS.Store.FileSystem("thumbnail", { transformWrite: function(fileObj, readStream, writeStream) { gm(readStream, fileObj.name()).autoOrient().resize('96', '96' + '^').gravity('Center').extent('96', '96').stream().pipe(writeStream); } }), new FS.Store.FileSystem("public"), ] });
server.js
Meteor.methods({ 'crop': function (fileId, selection) { var file = Images.findOne({ _id: fileId }), read = file.createReadStream('public'), write = file.createWriteStream('public'); gm(read) .crop(selection.width, selection.height, selection.left, selection.top) .stream() .pipe(write); } });
client.js
Template.editor.events({ 'click #crop': function () { var fileId = '123456789', selection = { height: 100, width: 100, top: 10, left: 10 }; Meteor.call('crop', fileId, selection); } });
Update
As Christian recommended, I use a tmp file for writeStream because writeStream cannot be the same as readStream, which caused an empty result.
But after writing to the tmp file, its contents must be copied back to the shared storage. How to do it?
Meteor.methods({ 'crop': function (fileId, selection) { var fs = Meteor.npmRequire('fs'), file = Images.findOne({ _id: fileId }), read = file.createReadStream('public'), filename = '/tmp/gm_' + Date.now(), tmp = fs.createWriteStream(filename); gm(read) .crop(selection.width, selection.height, selection.left, selection.top) .stream() .pipe(tmp);
Update 2 I tried this:
// Add temp store new FS.Store.FileSystem("temp") // Method Meteor.methods({ 'crop': function (fileId, selection) { var file = Images.findOne({ _id: fileId }), read = file.createReadStream('public'), temp = file.createWriteStream('temp'); gm(read) .crop(selection.width, selection.height, selection.left, selection.top) .stream() .pipe(tmp) .on('end', function () { var tmpread = file.createReadStream('temp'), write = file.createWriteStream('public'); gm(tmpread).stream().pipe(write); }); } });