Javascript 使用graphicsmagick在collectionFS中出现意外的空writestream
我使用CollectionFS管理图像。此外,我正在使用graphicsmagickJavascript 使用graphicsmagick在collectionFS中出现意外的空writestream,javascript,meteor,graphicsmagick,collectionfs,Javascript,Meteor,Graphicsmagick,Collectionfs,我使用CollectionFS管理图像。此外,我正在使用graphicsmagickgm()来处理图像 现在我想裁剪一个已经保存的图像。因此,在单击事件时,将调用一个服务器方法,该方法执行crop()。但这样做之后,在集合中我发现一个空图像,size=0在正确的日期更新 我不明白,我做错了什么 shared.js Images = new FS.Collection("images", { stores: [ new FS.Store.FileSystem("thumbn
gm()
来处理图像
现在我想裁剪一个已经保存的图像。因此,在单击事件时,将调用一个服务器方法,该方法执行crop()。但这样做之后,在集合中我发现一个空图像,size=0
在正确的日期更新
我不明白,我做错了什么
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"),
]
});
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);
}
});
Template.editor.events({
'click #crop': function () {
var fileId = '123456789',
selection = { height: 100, width: 100, top: 10, left: 10 };
Meteor.call('crop', fileId, selection);
}
});
server.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"),
]
});
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);
}
});
Template.editor.events({
'click #crop': function () {
var fileId = '123456789',
selection = { height: 100, width: 100, top: 10, left: 10 };
Meteor.call('crop', fileId, selection);
}
});
client.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"),
]
});
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);
}
});
Template.editor.events({
'click #crop': function () {
var fileId = '123456789',
selection = { height: 100, width: 100, top: 10, left: 10 };
Meteor.call('crop', fileId, selection);
}
});
更新
根据Christian的建议,我正在为writeStream使用一个tmp文件,因为writeStream不能与readStream相同,这导致了空结果
但在写入tmp文件后,必须将其内容复制回公共存储。我该怎么做
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
}
});
更新2
我试过这个:
// 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);
});
}
});
不能读写同一个文件。这相当于
cat test | grep 1 > test
在外壳上。您可以尝试一下,然后看到test
将为空
您需要在crop
方法中创建一个中间的临时文件
假设这确实是问题所在,那么这是一种方法(未经测试):
那么这有什么区别呢?你试过了吗?有效吗?我不是streams方面的专家,但就我对它们的理解而言,如果它是这样的话可能会很幸运——它可能适用于在从缓冲区开始写入之前作为一个整体进行缓冲的小文件,但不适用于较大的文件。但谁知道呢,也许collectionfs内部做了一些聪明的事情来允许这样做。无论如何,我不认为我会相信这一点。当你测试这个的时候,让我知道你发现了什么。。请举例说明如何使用临时流?完成后,如何将
tmp
复制到write
,并清空tmp
?真的吗?你要求所有这些额外的工作,而你甚至没有投票或接受答案?我相信你会在某个地方找到最后一个问题的答案。它只是将一个文件复制到您已有的流中;-)