Loopback-component-storage:如何在上传到 Amazon S3 之前将图像转换为缩略图

Loopback-component-storage: How to convert image to thumbnail before uploading to Amazon S3

我正在使用 环回组件存储 将图像上传到服务器。

我想将通过服务器上传的每个图像转换为缩略图视图并将其保存到容器中。 最初我使用本地文件存储来存储文件,一切正常。

在文件存储中,我使用 "quickthumb" 将图像转换为缩略图,然后将原始图像和缩略图大小的图像保存到容器中。

但现在我想使用 amazon S3 和环回组件存储来存储我的图像。按照文档,我可以轻松地将图像上传到 amazon S3 存储桶。但我无法弄清楚如何将图像调整为缩略图视图并将不同版本的图像与原始图像一起存储在 Amazon S3 服务器上。

这是我在使用文件存储实现它时所做的。

现在将其图像转换为缩略图大小

使用 quickthumb

下面是我如何将它与环回一起使用。

common/models/container.js

module.exports = function(Container) {

    var qt = require('quickthumb');

    Container.afterRemote('upload', function(ctx, res, next) {

        var file = res.result.files.file[0];
        var file_path = "./server/storage/" + file.container + "/" + file.name;
        var file_thumb_path = "./server/storage/" + file.container + "/thumb/" + file.name;

        qt.convert({
            src: file_path,
            dst: file_thumb_path,
            width: 100
        }, function (err, path) {

        });

        next();
    });

};

但是现在要在将图像上传到 S3 服务器之前实现调整图像大小,我需要一些 express 之类的语法,例如 req.files.image 但这在环回中是不可能的? 请帮忙。

您检查过 Strongloop 挂钩 https://docs.strongloop.com/display/public/LB/Adding+logic+to+models 了吗?您可以尝试在调用存储组件之前创建一个 Hooks

您可以完成您的尝试,但需要三个步骤。

首先,使用loopback-component-storage将文件上传到本地。一旦有了它,您就可以根据需要对图像进行尽可能多的调整。但是你会想要给图像一些唯一的名称以避免冲突。

其次,使用 AWS Node SDK 将这些新图像推送到您的 S3 存储桶。

最后,删除本地文件,自行清理。

这很简单。查看我为解决此类问题而整理的这个食谱:

https://github.com/dashby3000/recipe-s3-image-uploader

干杯!

丹尼斯

谢谢。 @Dennis 的回答。 我也发现了自己的另一种方式,我正在发布它。

Container.js

    var fs = require('fs');
    //Formidable to modify the form obtained as requests.
    var IncomingForm = require('formidable');
    //Imager for sending and modifying image to amazon
    var Imager = require('imager');

    Container.beforeRemote('upload', function(ctx,  modelInstance, next){
       var app       = Container.app;
       var container = ctx.req.params.container;
       //IF u have large image then. use this to avoid timeout..    
       ctx.req.connection.setTimeout(16000);

       //Checking if the container name is valid or not..
       var Customer = app.models.Customer;
       //http://apidocs.strongloop.com/loopback/#persistedmodel-exists
       //Now manually uploading to the provider and first converting the file to the thumbnail..
       upload(app, ctx.req, ctx.res, function(err, data){
         console.log("Image loaded successfully..");
       });                      

    });//beforeRemote








    //For handling the upload 
    var upload = function(app, req, res, options, cb) {
        var storageService =  app.dataSources.presImage.connector;
        if (!cb && 'function' === typeof options) {
             cb = options;
             options = {};
        }
        if (storageService.getFilename && !options.getFilename) {
           options.getFilename = storageService.getFilename;
        }
        if (storageService.acl && !options.acl) {
           options.acl = storageService.acl;
        }
        if (storageService.allowedContentTypes && !options.allowedContentTypes) {
           options.allowedContentTypes = storageService.allowedContentTypes;
        }
        if (storageService.maxFileSize && !options.maxFileSize) {
           options.maxFileSize = storageService.maxFileSize;
        }
        return handler(app, storageService.client, req, res, options, cb);
    }


   //Using handler for form parsing.. 
   var handler = function (app, provider, req, res, options, cb) {
        if (!cb && 'function' === typeof options) {
        cb = options;
        options = {};
        }

        if (!options.maxFileSize) {
        options.maxFileSize = defaultOptions.maxFileSize;
        }

        var form = new IncomingForm(options);

        var fields = {};
        var files = [];


          form
            .on('field', function(field, value) {
              fields[field] = value;
            })
            .on('file', function(field, file) {
              //Now upload the file to the amazon server.. 
              uploadToCloud(app,  fields.container, res, cb);
            })
            .on('end', function(name, file) {
                console.log("END-> File fetched from user phone.\n");
            });

          form.parse(req);
    }





   var uploadToCloud = function(app,  container, res, callback ){
      var fileName, extension;
      var time = new Date();
      time = time.getTime();
      fileName = '' + container + '_' + time;

      imagerConfig = {
         variants: {
            items: {
              rename: function (filename) {
                 return fileName + "." + extension;
              },

              resize: {
                 thumb: "200x200",
                 original: "100%"
              }
          }
       },

      storage: {
        S3: {
          key: 'AMAZON KEY',
          secret: 'AMAZON SECRET',
          bucket: 'YOUR BUCKET NAME HERE',
          storageClass: 'REDUCED_REDUNDANCY',
          secure: false
        }
      },
      debug: true
    }

    CHECK IF FILE IS IMAGE ONLY..
    var pattern = /^image\/(.+)$/;
    extension = pattern.exec(path.type);
    try{
        if(extension.length){
             extension = extension[1];
        }else{
             throw "Error. Only image type file is permitted";
        }   
      }catch(err){
           throw "Error getting extension of file..";
      }


      if(!extension || extension == 'jpeg'){
           extension = "jpg";   
      }

      imager = new Imager(imagerConfig, 'S3') // or 'S3' for amazon
      imager.upload([path], function (err, cdnUri, files) {
           // do your stuff
           if(err) throw err; 
           console.log("Successfully saved to the amazon server..");
           var fileArr = [];
           for(var i=0; i < files.length; i++){
                //Preparing the order object..
                fileArr.push({
                    name: files[i],
                    container: container
                }); 
            }

            //Sending the result fast..
            //Dont wait for image to get upload..
            res.send({
               result:{
                  files:{
                    file:fileArr
                  }
               } 
            }); //res.status  
            callback();
            //Now deleting the original file here...path is "os.tmp()"

       }, 'items');

   }//uploadToCloud..

Datasource.json

{
  "db": {
    "host": "",
    "port": 0,
    "database": "",
    "password": "",
    "name": "db",
    "connector": "memory",
    "user": ""
  },
  "Image": {
    "name": "Image",
    "connector": "loopback-component-storage",
    "provider": "amazon",
    "key": "YOUR AMAZON KEY",
    "keyId": "YOUR AMAZON KEY ID",
    "maxFileSize": "15728640"
  }
}