Skip to content

Commit

Permalink
file uploading and serving
Browse files Browse the repository at this point in the history
  • Loading branch information
eprochasson committed Jul 9, 2013
1 parent cded004 commit b793d78
Show file tree
Hide file tree
Showing 21 changed files with 228 additions and 68 deletions.
2 changes: 2 additions & 0 deletions .meteor/packages
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ router
email
i18n
momentjs
collectionFS
imagemagick
Binary file added [object Object]
Binary file not shown.
24 changes: 22 additions & 2 deletions client/helpers/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,34 @@ Meteor.Router.add({
}
}
},
'/profile': 'profile',
'/profile': {
as: 'profile',
to: 'profile',
and: function(){ Session.set('currentUserProfile', null)}
},
'/profile/edit': 'editProfile',
'/profile/:_id': {
as: 'profile',
to: 'profile',
and: function(id){ Session.set('currentUserProfile', id);}
},
'/settings': 'settings'
'/settings': 'settings',
'/images/:_id': function(id){
console.log(id);


Pictures.retrieveBlob(id, function(fileItem) {
console.log('file', fileItem);
if (fileItem.blob) {
return fileItem.blob;
// saveAs(fileItem.blob, fileItem.filename);
} else {
return fileItem.file;
// saveAs(fileItem.file, fileItem.filename);
}
});
},
'*': 'p404'
});

Meteor.Router.filters({
Expand Down
7 changes: 6 additions & 1 deletion client/main.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Meteor.subscribe('questions');
Meteor.subscribe('myData');
Meteor.subscribe('myPictures');

//Deps.autorun(function () {
// userProfileHandle = Meteor.subscribe("userProfile", Session.get("currentUserProfile"));
//});
Deps.autorun(function () {
userProfileHandle = Meteor.subscribe("userProfile", Session.get("currentUserProfile"));
userProfileHandle = Meteor.subscribe("oneUserProfile", Session.get("currentUserProfile"));
userPictureHandle = Meteor.subscribe("oneUserPictures", Session.get("currentUserProfile"));
});
3 changes: 3 additions & 0 deletions client/views/404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template name="p404">
<h1>This is not the page you're looking for</h1>
</template>
6 changes: 5 additions & 1 deletion client/views/profile/editProfile.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

<h1>Hello World. PE</h1>


{{> profile_picture_edit}}

{{> profile_pictures}}

<form id="editProfile">
{{#each questions}}
{{{callPartial tpl this 'form_field_text'}}}
Expand All @@ -10,6 +15,5 @@ <h1>Hello World. PE</h1>
<button class="btn btn-submit">{{Lex 'default.save'}}</button>
</form>

{{> profile_picture_edit}}

</template>
8 changes: 7 additions & 1 deletion client/views/profile/editProfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ var validateControlGroup = function(input){

Template.editProfile.helpers({
questions: function(){
return questions = Questions.find({}, {sort: {sortorder: 1}});
return Questions.find({}, {sort: {sortorder: 1}});
},
pictures: function(){
return Pictures.find({owner: Meteor.userId()}, {sort: {sortorder: -1}});
},
image: function(){

}
});

Expand Down
5 changes: 2 additions & 3 deletions client/views/profile/profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ <h1>This is your profile</h1>
<h1>{{Lex 'default.title_profile' name=currentUser.profile.name}}</h1>
{{/if}}

{{> profile_pictures}}

<ul>
<li>{{Lex 'question.name'}}: {{question 'name'}}</li>
<li>Age: {{age}}</li>
</ul>



</template>
3 changes: 3 additions & 0 deletions client/views/profile/profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,8 @@ Template.profile.helpers({
} else {
return 0;
}
},
pictures: function(){
return Pictures.find({}, {sort: { sortorder: -1 }});
}
});
18 changes: 9 additions & 9 deletions client/views/profile/profile_picture_edit.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
Template.profile_picture_edit.events({
'change input': function(e){
e.preventDefault();
_.each(e.srcElement.files, function(file){
Meteor.uploadPicture(file, file.name, function(err, res){
if(err){
console.log(err);
} else {
console.log('weeeeeeeeee', res);
}
});
})
var files = e.target.files;
_.each(files, function(file){
var res = Pictures.storeFile(file, {});
if(res){
return res
} else {
throw new Meteor.Error(500, 'Something went wrong');
}
});
}
});
11 changes: 11 additions & 0 deletions client/views/profile/profile_pictures.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<template name="profile_pictures">
{{#each pictures}}
{{#if thumbnail50x50}}
<img src="{{thumbnail50x50}}">
{{else}}
No Thumbnail available.
{{/if}}
{{else}}
You haven't upload any picture
{{/each}}
</template>
20 changes: 20 additions & 0 deletions client/views/profile/profile_pictures.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Template.profile_pictures.helpers({
pictures: function(){
return Pictures.find({owner: Meteor.userId()}, {sort: {sortorder: -1}});
},
original: function(){
if(this.fileHandler && this.fileHandler.save){
return this.fileHandler.save.url;
} else {
return null;
}
},
thumbnail50x50: function(){
console.log('fileHandler', this.fileHandler);
if(this.fileHandler && this.fileHandler.thumbnail50x50){
return this.fileHandler.thumbnail50x50.url;
} else {
return null;
}
}
});
44 changes: 44 additions & 0 deletions collections/pictures.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Pictures = new CollectionFS('pictures', {autopublish: false});

Pictures.allow({
insert: function(userId, myFile) {
return Pictures.find({owner: userId}).count() < 8 && userId && myFile.owner === userId;
},
update: function(userId, files, fields, modifier) {
return _.all(files, function (myFile) {
return (userId == myFile.owner);
}); //EO iterate through files
},
remove: function(userId, files) { return false; }
});

var isImage = function(type){
return type == 'image/jpeg';
};

Pictures.fileHandlers({
save: function(options){
console.log('Running fileHandler save');
if (options.fileRecord.length > 5000000 || !isImage(options.fileRecord.contentType)){
return null;
}
return { blob: options.blob, fileRecord: options.fileRecord };
},
thumbnail50x50: function(options){
console.log('running thumbnail 50x50');
if (isImage(options.fileRecord.contentType)){
console.log('resizing');
var res = Imagemagick.resize({
srcData: options.blob,
width: 50,
height: 50,
quality: 0.8,
format: 'jpg'
});

return { blob: res, fileRecord: options.fileRecord };
} else {
return null;
}
}
});
17 changes: 0 additions & 17 deletions lib/save_file.js
Original file line number Diff line number Diff line change
@@ -1,17 +0,0 @@
/**
* @blob (https://developer.mozilla.org/en-US/docs/DOM/Blob)
* @name the file's name
* @type the file's type: binary, text (https://developer.mozilla.org/en-US/docs/DOM/FileReader#Methods)
*
* TODO Support other encodings: https://developer.mozilla.org/en-US/docs/DOM/FileReader#Methods
* ArrayBuffer / DataURL (base64)
*/
Meteor.uploadPicture = function(blob, name, callback) {
var fileReader = new FileReader(),
method = 'readAsBinaryString', encoding = 'binary';

fileReader.onload = function(file) {
Meteor.call('uploadPicture', file.srcElement.result, name, '', encoding, callback);
};
fileReader[method](blob);
};
76 changes: 76 additions & 0 deletions server/publications.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,80 @@ Meteor.publish("userProfile", function(userId){
};
}
return Meteor.users.find({_id: userId}, {fields: fields});
});


Meteor.publish("oneUserProfile", function(userId){

// Send over the picture attached to a user depending on permission.
var source = Meteor.users.findOne(this.userId);
var target = Meteor.users.findOne({_id: userId, 'visible': 1});

var self = this;
var profileHandle = null, picturesHandles = [];
var profileType = 'public'; // Default: can only see default information.
var fields = {
'profile.name': 1,
'profile.gender': 1
};

if(target && target.friends && _.contains(target.friends, source._id)){
profileType = 'private'; // If the target is friend (or wants to be friend) with you, get the full profile.
fields = {
'profile': 1
};
}

function publishProfilePictures(profile){
var limit = {limit: 2, sort: {sortorder: -1}};
if(profileType == 'private'){
limit = {limit: 0, sort: {sortorder: -1}};
}
var pictures = Pictures.find({ type: 'profile', owner: userId}, limit);
picturesHandles[profile._id] = pictures.observe({
added: function(id, picture){
self.added('pictures', id, pictures);
}
})
}

profileHandle = Meteor.users.find({_id: userId, visible: 1}, { fields: fields }).observe({
added: function(profile){
publishProfilePictures(profile);
self.added('users', profile._id, profile);
},
removed: function(id){
//stop observing changes on the profile;
picturesHandles[id] && picturesHandles[id].stop();
// Delete the profile
self.removed('users')
}
});

self.ready();

self.onStop(function(){
profileHandle.stop();
});
});

Meteor.publish('oneUserPictures', function(userId){
if(userId){
// Send over the picture attached to a user depending on permission.
var source = Meteor.users.findOne(this.userId);
var target = Meteor.users.findOne({_id: userId, 'visible': 1});

var limit = {limit: 2, sort: {sortorder: -1}};
if(target && target.friends && _.contains(target.friends, source._id)){
limit = {limit: 0, sort: {sortorder: -1}};
}

return Pictures.find({ owner: userId});
} else {
return [];
}
});

Meteor.publish('myPictures', function(){
return Pictures.find({owner: this.userId});
});
30 changes: 0 additions & 30 deletions server/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,36 +46,6 @@ Meteor.methods({
});
}
})
},
uploadPicture: function(blob, name, path, encoding) {

function cleanPath(str) {
if (str) {
return str.replace(/\.\./g,'').replace(/\/+/g,'').
replace(/^\/+/,'').replace(/\/+$/,'');
} else {
return '';
}
}
function cleanName(str) {
return str.replace(/\.\./g,'').replace(/\//g,'');
}
var path = cleanPath(path), fs = Npm.require('fs'),
name = cleanName(name || 'file'), encoding = encoding || 'binary',
chroot = Meteor.chroot || 'public/uploads';

var name = Meteor.FileUpload.getName(blob,name);

path = chroot + (path ? '/' + path + '/' : '/');

// TODO Add file existance checks, etc...
try{
fs.writeFileSync(path + name, blob, encoding);
} catch (e){
throw (new Meteor.Error(500, 'Failed to save file.', e));
}

return path+name;
}
});

4 changes: 3 additions & 1 deletion smart.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
"accounts-ui-bootstrap-dropdown": {},
"router": {},
"i18n": {},
"momentjs": {}
"momentjs": {},
"collectionFS": {},
"imagemagick": {}
}
}
Loading

0 comments on commit b793d78

Please sign in to comment.