Uso CollectionFS per la gestione delle immagini. Inoltre sto usando graphicsmagick gm()
per manipolare le immagini.writestream vuoto inatteso in collectionFS utilizzando graphicsmagick
Ora voglio ritagliare un'immagine già salvata. Pertanto, in un evento click viene chiamato un metodo server, che esegue il ritaglio(). Ma dopo averlo fatto, nella raccolta trovo un'immagine vuota con size=0
aggiornata alla data corretta.
Non vedo, quello che sto facendo male.
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);
}
});
Aggiornamento
Come consigliato da Christian Sto usando un file tmp per writeStream, perché lo stream di scrittura non può essere lo stesso del readStream - che ha causato il risultato vuoto.
Ma dopo aver scritto nel file tmp, il contenuto deve essere copiato nell'archivio pubblico. Come lo faccio?
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);
// After writing to tmp -> copy back to stream and delete tmp-file
}
});
Update 2 ho provato questo:
// 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);
});
}
});
Allora, qual è la differenza a questo? https://github.com/CollectionFS/Meteor-CollectionFS/wiki/How-to:-Convert-a-file-stready-stored – user3142695
hai provato e funziona? Non sono un esperto di streaming, ma il modo in cui li capisco potrebbe essere una fortuna se lo facesse, potrebbe funzionare per file di piccole dimensioni che vengono bufferizzati nel loro complesso prima che inizi la scrittura dal buffer, ma non per quelli più grandi. Ma chi lo sa, forse collectionfs fa qualcosa di intelligente internamente per permettere questo. In un modo o nell'altro, non penso che mi baserei su questo. Fammi sapere cosa scopri quando provi questo. –
Hmm .. potresti per favore fare un esempio di come useresti un flusso temporaneo? – user3142695