sheila.ar
sheila.ar

Reputation: 57

Multiple FS Collection Meteor

I'm currently using Meteor collectionFS, to be able to upload images, the project works correctly, but it only works if I want to upload and see a single image. What I want is to select 2 or more images and to visualize correctly, in the input I am using the multiple attribute, but how do I see the images?

Client images.html

<template name="images">
    <div align="center">
      <form align="center" role="form">
        <div>
          <div>
            <span class="btn btn-success btn-file">
              <input type="file" accept=".gif,.jpg,.png" class="myFileInputimagepub" id="image" multiple/>
            </span>
          </div>
          <div>
              <img src="{{currentUser.photo.image}}" alt="Image" width="60px" height="60px"  value=''/>
          </div>
        </div>
      </form>
    </div>
  </template>

images.js

import './images.html';

Template.images.events({
  'change .myFileInputimagepub':function(evt,tmpl){
    FS.Utility.eachFile(event,function(file){
      fileImagespub.insert(file,function(err,fileObj){
        if(!err){
          var userId = Meteor.userId();
          var imageurl = {
            ‘photo.image':'/cfs/files/fileimages/' + fileObj._id
          };
          setTimeout(function(){
            Meteor.users.update(userId,{$set:imageurl});
          },200);
        }
      })
    })
  },


});

Server

permissions/ permissions.js

Meteor.users.allow({
  insert:function(userId,doc){
    return userId;
  },
  update:function(userId,doc,fields,modifier){
    return userId && doc._id === userId;
  },
  remove:function(userId){
    return userId;
  }
});

fileImagespub.allow({
  insert:function(){
    return true;
  },
  update:function(){
    return true;
  },
  remove:function(){
    return true;
  },
  download:function(){
    return true;
  }

Both/collections/fileupload.js

var filepubimagestorage = new FS.Store.GridFS("fileimagesp");
fileImagespub = new FS.Collection("fileimages",{
  stores:[filepubimagestorage]
});

Upvotes: 1

Views: 284

Answers (1)

Jankapunkt
Jankapunkt

Reputation: 8413

Welcome to SO. Look at the following part of your code:

FS.Utility.eachFile(event,function(file){
  fileImagespub.insert(file,function(err,fileObj){
    if(!err){
      var userId = Meteor.userId();
      var imageurl = {
        ‘photo.image':'/cfs/files/fileimages/' + fileObj._id
      };
      setTimeout(function(){
        Meteor.users.update(userId,{$set:imageurl});
      },200);
    }
  })

You are overriding the imageurl for the user because you use $set to replace the field. You should treat it as an array and push the image urls to it. If there is only one image you end up with an array of size 1, so fine for all.

To do that you may use Mongo push for that:

FS.Utility.eachFile(event,function(file){
  fileImagespub.insert(file,function(err,fileObj){
    if(!err){
      var userId = Meteor.userId();
      setTimeout(function(){
            Meteor.users.update(userId,{$push:{'photo.image':'/cfs/files/fileimages/' + fileObj._id}});
      },200);
    }
  })
  1. Note, that this is not a final solution, since it neither solves use case like replacing an image, removing images etc. (you should try them for yourself and come back here if you have trouble).

  2. Note, that the other uploads, that used the old field photo.image are now not usable anymore. Users, that have already photos.image may throw an error on push attempt (expected array got string). This is a great example, where design problems should be solved first, before starting to code in order to avoid such a problem. Because you are now dealing with multiple images you should also consider to rename photo.image to photo.images. I left it the original way for better understanding.

  3. Note, that You also need to makes changes in the template where you iterate this array:

<div>
{{#each currentUser.photo.image}}
    <img src="{{this}}" alt="Image" width="60px" height="60px"  value=''/>
{{/each}}
</div>

However, there are still a sidenote to that. First, this is all client side code and you should validate your data before trusting any client side uploads.

Allow/deny is discouraged to use and Meteor methods should be used instead. If you still insist on using allow/deny, please also read the latest security blog article on allow/deny vlunerabilties.

Upvotes: 1

Related Questions