CollectionFS getting url of image file - meteor

Hi am using CollectionFS to upload and store images.
Uploading and storing the file is successful. I can retrieve file object from publication. But am unable to get URL for file. I need url for img tag
Following is how I declared collections.
Images = new FS.Collection("images", {
stores: [new FS.Store.GridFS("images")]
});
In browser console following code returns FS.File object
NewsImages.find().fetch()[0]
FS.File {createdByTransform: true, _id: "3kqLZRdLD33dKir2M", original: Object, chunkSize: 2097152, chunkCount: 0…}
But url is returning null.
NewsImages.find().fetch()[0].url()
null
Is there any extra work needed to generate URL?
More Details
I am using following allow rules.
NewsImages.allow({
//more others
download: function(){
if(Meteor.userId()){
return true;
}else{
return false;
}
}
});
I am getting following exception.
Meteor.userId can only be invoked in method calls. Use this.userId in publish functions.
I replaced Meteor.userId() with this.userId but this.userId is undefined.

Use a callback on saving the image and then put the image id into another
collection. Rough pseudo code...
Images.insert(yourFsFile, function (error, fileObj) {
if (error) {
// cry!
}
_.extend(yourItem, {imageId: fileObj._id});
Meteor.call('otherCollectioInsert', yourItem, function(error, result) {
if (error) {
// cry again!
}
// should have saved the image id so you can use the url
// http://www.you.com/cfs/files/images/the_id_you_saved
});
});
I hope this helps

Related

Can't upload image to EC2 Instance with CollectionFS/GridFS ERR_CONNECTION_REFUSED

I'm working on a simple Meteor app which manages profile pictures, while working in local my project is working fine.
But after deploying it on an AWS EC2 instance (With Meteor-Up), every works fine, except the image upload.
I'm using CollectionFS (cfs:standard-packages, cfs:gridfs).
Here's the code :
// Collection definition
Images = new FS.Collection("images", {
stores: [new FS.Store.GridFS("original")]
});
Images.allow({
'insert': function () {
return true;
},
'update': function () {
return true;
},
'download':function(){
return true;
}
});
// Event to upload the image
"click .js-validate"(event, instance){
Images.insert(instance.file.get(), function (err, fileObj) {
if(err){
console.log("Error");
console.log(err);
}else{
console.log("No error");
console.log(err);
Meteor.call('updatePP', fileObj._id, function(){
Modal.hide("Modal_update_pp");
});
}
});
}
The security rules for my EC2 instance :
And here's the error showing when i execute the event which execute the Images.insert function.
The error ERR_CONNECTION_REFUSED is showing.
I'm able to get the image id, but the image isUploaded function return false :
Why am i having this error and how can i solve this problem ?
Is it due to my EC2 configuration or the code inside my Meteor Project ? Thanks !
I’d suggest to switch to ostrio:files which is fully documented and up to date. GridFS is really old and buggy. You can then save your files securely to a S3 instance and keep your MongoDB size low.

Meteor reading data from a file stored on server

I want to show some data points on the client side, and I want to get the latitude, longitude and summary from a file stored on the server.
I have read a lot of posts saying to use papaParse using Meteor methods but I am not able to make it work.
Can you guys point me to right direction, my questions are:
In which folder to should I store a .txt, .csv or .json file in Meteor?
How to access it from the client and return the read data to client for display.
You can put your static files into private folder on the server and get them through Assets.
For exmaple, you have a data.json file in your private folder.
Method to get this data:
Meteor.methods({
getData() {
return JSON.parse(Assets.getText('data.json'));
}
});
You can now call this method on the client:
Meteor.call('getData', function(err, res) {
console.log(res);
});
UPD
Ok, how to display it.
Meteor.call runs async, so we will use reactivity to update our view on result.
Here is how we can display data on ourData template.
<template name="ourData">
<!-- Here you may want to use #each or whatever -->
<p>{{ourData}}</p>
</template>
Template.ourData.onCreated(function() {
this.ourData = new ReactiveVar();
Meteor.call('getData', (err, res) => {
if (err) {
console.error(err);
} else {
// Putting data in reactive var
this.ourData.set(res);
}
});
});
Template.ourData.helpers({
ourData: function() {
// Helper will automatically rerun on method res
return Template.instance().ourData.get();
}
});
reactive-var package required or you can also use Session.

Meteor template updates before result of Meteor.users.update

I'm trying to figure out how to prevent a template from updating until Meteor.users.update() finishes.
First I'm trying to make sense of the documentation and the use of an optional callback argument in order to sort out what is happening.
Here is what I have:
Meteor.users.update(Meteor.userId(),
{$set:{'profile.reviewList': []}},
[],
function(err, result){
if (err){
console.log('oh no!');
} else {
console.log('Result achieved: '+this.profile.reviewList);
}
});
Currently the console.log('Result achieved: '+this.profile.reviewList); always returns something like ...TypeError: Cannot read property 'reviewList' of undefined... the first time though which tells me its firing before the result comes back.
I'm sure I'm not implementing the callback properly, but I was attempting to model this answer: How do you ensure an update has finished in meteor before running a find?
I'd really just like to delay the re-rendering of the associated template until the property gets created.
Any help will be greatly appreciated.
You assume that scope (this) in callback function return user object, which is wrong.
If you want to get user object in that callback simply query it there:
var user = Meteor.users.find(Meteor.userId()).fetch()
Another thing, you passed empty array as 2nd argument which is not needed.
Meteor.users.update(
Meteor.userId(),
{
$set: {
'profile.reviewList': 'testData'
}
},
function(err, result) {
if (err) {
console.log('oh no!');
} else {
var user = Meteor.users.find(Meteor.userId()).fetch();
console.log('Result achieved: ' , user && user.profile && user.profile.reviewList);
}
}
);

access data from iron-router in rendered function

I'm trying to access data passed from iron router in the javascript function
router.js
this.route('editOrganization', {
path: '/editOrganization',
waitOn: function() {
return [
Meteor.subscribe('organization', this.userId)
];
},
data: function() {
return Organizations.findOne();
}
});
now if I wanted to access a property of organization in html (editCompany.html) I can do the following
{{name}}
but how do I access that same property in the js file
Template.editOrganization.rendered = function() {
//how do I access name?
}
UPDATE:
so if I click a link to edit organization I can get the value via
this.data.name
However, if I reload the page (same url) it throws an error saying data is null.
It is accessible through the rendered function context.
Template.editOrganization.rendered = function() {
var name = this.data && this.data.name;
};
This is confusing for many people but you need to configure the router to actually wait for the subscriptions you returned with waitOn.
Router.onBeforeAction('loading')
You can read the author's explanation here:
https://github.com/EventedMind/iron-router/issues/554#issuecomment-39002306

Meteor: Subscription doesn't work

I'm trying to get a document from the server and display it on the client but the subscription always return a collection with no document.
// server/publications.js
Meteor.publish('myPages', function() {
return Pages.findOne({userId: this.userId});
});
// collection/pages.js
MyPages = new Meteor.Collection('myPages');
// client/main.js
Meteor.subscribe('myPages');
// client/view.js
Template.myView.helpers({
myPages: function(e, t) {
console.debug(MyPages.find({}));
return MyPages.find({});
}
});
You cannot move a document between collections via a subscription. If you subscribe to get a document that's in Pages collection, defined as new Meteor.Collection("pages"), then no matter how your pubsub channels look like, on the client the document will be found in the collection defined as new Meteor.Collection("pages"). So remove all traces of MyPages and use Pages on the client as well. You'll find the document there.
I don't think you can use findOne to publish collections: it doesn't return a cursor but an actual object.
Does this not work?
Meteor.publish('myPages', function() {
return Pages.find({userId: this.userId});
});
or, if necessary:
Meteor.publish('myPages', function() {
return Pages.find({userId: this.userId}, {limit: 1});
});

Resources