I'm trying to use the cfs:graphicsmagick package to generate thumbnails but all that is generated is an empty image.
When I start the server things look good:
I20150108-10:43:14.698(-8)? => GraphicsMagick found
I20150108-10:43:14.901(-8)? available
=> Meteor server restarted
but it seems gm is not available:
if (gm.isAvailable) {
console.log("gm is available");
}
and the console throws out an error:
Uncaught TypeError: Cannot read property 'isAvailable' of undefined
Look into docs, seems like the gm scope its just available on the server side, so there is not problem here, you are having the console.log, pretty find
now you can use, on the fsCollection like this
Images = new FS.Collection("images", {
stores: [
new FS.Store.FileSystem("images"),
new FS.Store.FileSystem("thumbs", {
transformWrite: function(fileObj, readStream, writeStream) {
// Transform the image into a 10x10px thumbnail
gm(readStream, fileObj.name()).resize('10', '10').stream().pipe(writeStream);
}
})
],
filter: {
allow: {
contentTypes: ['image/*'] //allow only images in this FS.Collection
}
}
});
remember gm its just available on the server, so use it on /server or use on if(isServer)
Try this
if (Meteor.isServer) {
if (gm.isAvailable) {
console.log("gm is available and this console.log was printed from my own code");
}
}
Tell me if works
Update answer
If you are declaring FS.collection on both server/client i recommend you declare collection on /lib/collection.js like this
//collections.js
Adopcion = new FS.Collection("Adopcion", {
stores: [
new FS.Store.FileSystem("images"),
new FS.Store.FileSystem("thumbs", {
transformWrite: function(fileObj, readStream, writeStream) {
// Transform the image into a 10x10px thumbnail
gm(readStream, fileObj.name()).resize('10', '10').stream().pipe(writeStream);
}
})
]
});
and on the same file make the subscription
//collection.js
//Subscribe
if(Meteor.isClient) {
Meteor.subscribe('Adopcion');
}
And now on /server/publish.js you only make the publish function
//Publish methods
Meteor.publish('Adopcion', function(){
return Adopcion.find();
});
With that there is no need of Meteor.methods({}) and the first thing meteor will load its the collection, and they will be available on both client/server
Take a look and tell me if works for you
Related
Model code:
ProfileImage = new FS.Collection('profileImage', {
stores: [
new FS.Store.FileSystem('profile-image')
],
filter: {
maxSize: 524288,
allow: {
extensions: ['png', 'jpg', 'jpeg'],
contentTypes: ['image/png', 'image/jpg', 'image/jpeg']
}
}
});
Insertion code:
ProfileImage.insert('http://graph.facebook.com/' + user.services.facebook.id + '/picture/?type=large', function(error, imageObj) {
console.log(imageObj);
});
with that code I get a file name like this: profileImage-iiGE2ouSifuu3iLjq-undefined .
the name is undefined and without extension at all.
Try this (copied from a project of mine. this works):
//this is the event for when you select an image
'change .yourfileinput': function (event, template) {
FS.Utility.eachFile(event, function (file) {
var yourFile = new FS.File(file);
Images.insert(yourFile, function (err, fileObj) {
var fileUrl = '/cfs/files/profile-image/'+fileObj._id;
Session.set('fileUrl', fileUrl);
});
});
},
//form submit event
"submit .your-form-class": function (event) {
var whichUser = Meteor.userId() //or you could just write this inside the method call instead of adding a variable
var profilePicture = Session.get('fileUrl');
Meteor.call("yourMethod", whichUser, profilePicture);
}
Of course, you need to play on it/customise to your needs. ^ is for default file path of cfs:filesystem.
I switched to gridfs though and I highly recommend it.
Edit your question with all your code if it doesn't work and we'll find a solution. File upload was the biggest problem I encountered along the way.
I am new to meteor, what I am trying to do is upload an image store it in the file system and then simply display the images I have loaded.
I am also creating a thumbnail of the images I am uploading like this
var createThumb = function(fileObj, readStream, writeStream) {
// Transform the image into a 10x10px thumbnail
gm(readStream, fileObj.name()).resize('10', '10').stream().pipe(writeStream);
};
Images = new FS.Collection("images", {
stores: [
new FS.Store.FileSystem("thumbs", { transformWrite: createThumb }),
new FS.Store.FileSystem("images", {path: "~/uploads"})
],
filter: {
allow: {
contentTypes: ['image/*'] //allow only images in this FS.Collection
}
}
});
I have couple of issues, first of all I want to specify a path on the computer where I can store the image. I am not sure how I do that. I have created a public folder in the project and would like to store the images there.
When I start doing the thumbnail thing it is not working at all. I am not sure if the images (both original and the thumbnail) are even uploaded.
Can anyone explain or point towards me a good tutorial?
Here are some tutorials
From RaiX
Collection FS Wiki Page
Blog Post by Victor Leung
I haven't used Collection FS in a few months, but this code below should work.
Images = new FS.Collection("images", {
stores: [
new FS.Store.FileSystem("thumbs", { path: "~/public/thumbs", transformWrite: createThumb }),
new FS.Store.FileSystem("images", { path: "~/public/images" })
],
filter: {
allow: {
contentTypes: ['image/*'] //allow only images in this FS.Collection
}
}
});
Possible duplicate: Meteor collectionfs insert server side
I have multiple image collections using GridFS to store files. If I use "Images" as name for the collection everything works fine, but as soon as I change the name I'm getting GET http://localhost:3000/cfs/files/PlayerImages/zo4Z7rnYLb32MLYkM/taylor.jpg 403 (Forbidden)
(And for example, this one does work: http://localhost:3000/cfs/files/Images/7j9XAEebGctuivGhz/see-more.png)
This is how I defined my collections:
function createImageCollection(name,transform){
var collectionName = name + 's';
var storeName = name + 'Store';
var options = {
filter: {
allow: {
contentTypes: ['image/*'],
extensions: ['png', 'PNG', 'jpg', 'JPG', 'jpeg', 'JPEG']
}
}
};
if (Meteor.isServer) {
storeOptions = {
path: process.env.PWD + "/public"
};
// only add the transform when graphicsmagick is available
if(gm.isAvailable && typeof transform === 'function'){
storeOptions.transformWrite = transform;
}
options.stores = [new FS.Store.GridFS(storeName,storeOptions)];
} else {
options.stores = [new FS.Store.GridFS(storeName)];
}
return new FS.Collection(collectionName,options);
}
// and finally create them
// THIS FIRST ONE WORKS JUST FINE
Images = createImageCollection('Image',imageResizeTimeline); // default resize is timeline, nothing bigger then that?
BackgroundImages = createImageCollection('BackgroundImage',imageResizeBackground);
PlayerImages = createImageCollection('PlayerImage',imageResizePlayer);
LogoImages = createImageCollection('LogoImage',imageResizeLogo);
And I also added allow/deny rules for each collection:
var ImagePermissions = {
insert: function () {
return true;
},
update: function () {
return true;
},
download: function () {
return true;
},
remove: function () {
return false;
},
fetch: null
};
Images.allow(ImagePermissions);
PlayerImages.allow(ImagePermissions);
BackgroundImages.allow(ImagePermissions);
LogoImages.allow(ImagePermissions);
On a sidenote, I am using autoform to generate forms, but I don't think the problem is located in there because "Images" works.
Must I add this path to some "routing" or "config" files? Maybe "Images" is added by default? (This project is set-up by someone else, but I don't think I missed anything he did.)
How to get file url for specific store using collectionFS in meteor?
I need to retrieve it in my onrendered code:
var url = Images.findOne(filesList[index].id).url();
This return me default store for Images, but in Images i have two store:
Images = new FS.Collection("images", {
stores: [fullImage, previewImage],
filter: {
allow: {
contentTypes: ['image/*']
},
onInvalid: function (message) {
if (Meteor.isClient) {
toastr.warning("Impossibile salvare l'immagine a causa di: " + message);
} else {
console.log(message);
}
}
}
});
I need to retrieve previewImage, i cannot use tag code because i need to download it in background on the client..
Just found a simple solution:
Images.findOne(filesList[index].id).url({store: 'preview'});
In my demo I'm using the https://github.com/tomitrescak/meteor-uploads package for image uploading and its working like a charm. Now I want to call my image processing function before the file is uploaded.
Once my image processing function is done, I want to start uploading the image to my local (that is already working by meteor-uploads package).
How it can be achieved?
I would switch over to using CollectionFS. They have image manipulation ( imagemagick, graphicsmagick) abilities for file file uploads. So when you define your collection using CollectionFS use:
Images = new FS.Collection("images", {
stores: [
new FS.Store.FileSystem("thumbs", { transformWrite: createThumb }),
new FS.Store.FileSystem("images"),
],
filter: {
allow: {
contentTypes: ['image/*'] //allow only images in this FS.Collection
}
}
});
var createThumb = function(fileObj, readStream, writeStream) {
// Transform the image into a 10x10px thumbnail
gm(readStream, fileObj.name()).resize('10', '10').stream().pipe(writeStream);
};
Notice that the createThumb is using graphicsmagick in the function createThumb (gm) to resize the image for you before inserting it into the collection images under the specific store thumbs.