keystonejs / keystone-storage-adapter-s3

⚠️ Archived - Legacy S3 Storage Adapter for KeystoneJS
MIT License
17 stars 55 forks source link

Multiple images? #16

Closed programmer4web closed 6 years ago

programmer4web commented 7 years ago

not an issue but can this be used or extended for Multiple Images? for front-end I use:

<input id="upload" type='file' name="File-image-1001" accept=".png,.jpg,.jpeg" multiple />
<input type="hidden" name="image" value="upload:File-image-1001">

on model:

    var s3Storage = new keystone.Storage({
          adapter: require('keystone-storage-adapter-s3'),
          s3: {
            path: 'some_path',
            region: process.env.S3_REGION,
            headers: {
              'x-amz-acl': 'public-read',
            },
          },
                schema: {
                    filename: true,
                    size: true,
                    mimetype: true,
                    path: true,
                    originalname: true,
                    url: true
                }
        });

MyModel.add({ image: { type: Types.File, storage: s3Storage } });

then on server side:

keystone.list('MyModel').updateItem( model, req.body, { files: req.files }, function(err){
     if(err) return error(err,'Some Error');
}
sktt commented 7 years ago

Wouldn't it make more sense if keystone.Field.Types.File has the option to support multiple files or there's a FileCollection type?

josh-hardman commented 7 years ago

Has there been any follow up or work arounds for this? I really need to upload multiple images to S3 just like I could with the CloudinaryImages type. Any help would be greatly appreciated!

programmer4web commented 7 years ago

the same way no, but I have used an different model Images and an relationship to that model: one model:

Image.add({
    img             : { type: Types.File, storage: s3Storage }
});
MyModel.add({
    files               : { type: Types.Relationship, ref: 'Image', many: true, note: 'Images from Users.' }
});

save route example:

new MyModel(data).save().then( function(mymodel){
         MyModel.findById( mymodel._id ).exec().then(function(mymodel){       //get mymodel unpopulated to avoid error

           keystone.list('MyModel').updateItem( mymodel, data, { files: req.files }, function(err){ // update the mymodel with files step 1
             if(err) return error(err,'Preview save error.');

             var ids = [],
               saveImage = function iteratee(item, callback) {
                 new Image({ img: item }).save().then( function(image){
                   Img.updateItem( image, { img: item }, { files: req.files }, function(err){
                     if(err) return error(err,'Client Design Image upload error.');

                     ids.push(image._id);
                     callback();
                   });
                 });
               },

               success = function(){  // After Images Saved Successfully
                 // console.log('Ids: ', ids);
                 mymodel.images = ids;
                 mymodel.save().then(function(){
                   // next operation here if any..
                 });
               };

             // console.log('Type: ', typeof(imgs));
             switch( typeof(imgs) ){
               case 'string': saveImage( imgs, success ); break;
               case 'object': async.eachSeries(imgs, saveImage, success); break;
               default:
                 mymodel.populate('ingredient container', function(err,mymodel){ 
                    //next operation here if any
                  });
             }

           }, function(err){ if(err) return error(err, 'MyModel update error.'); } );
         }, function(err){ if(err) return error(err, 'MyModel find error.'); } );
       }, function(err){ if(err) return error(err, 'MyModel save error.'); } );   
askdesigners commented 6 years ago

That's a decent workaround ^^ 👍