Loopback组件存储:如何在上传到Amazon S3之前将图像转换为缩略图

4
我正在使用 Loopback 组件存储 来上传图像到服务器。
我想将通过服务器上传的每个图像转换为 缩略图 并保存到容器中。 最初,我使用本地文件存储来存储文件,一切都很正常。
在文件存储中,我使用了 "quickthumb" 将图像转换为缩略图,然后将原始图像和缩略尺寸图像保存到容器中。
但现在我想使用 Loopback 组件存储将我的图像存储到 Amazon S3 中。按照文档,我可以轻松地将图像上传到 Amazon S3 存储桶。但我不知道如何将图像调整大小以适应缩略图,并在 Amazon S3 服务器上存储不同版本的图像及其原始图像。 以下是我在使用文件存储时的操作:
现在要将其转换为缩略图大小 使用 quickthumb 以下是我在 loopback 中使用它的方式。
引用: 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,但在loopback中不可能实现吗?请帮忙。

3个回答

5
你可以完成你想要的事情,但需要三个步骤。首先,使用loopback-component-storage在本地上传文件。一旦你将文件上传到本地,你可以对图像进行任意数量的调整。但你需要给图像一个独特的名称以避免冲突。其次,使用AWS Node SDK将这些新图像推送到你的S3存储桶中。最后,删除本地文件以清理。这很简单。查看我编写的解决此类问题的配方:

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

干杯!

Dennis


3

感谢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"
  }
}

@RobbinsGupta 我在服务器上有一个Images文件夹,我需要将其中的每个图像逐一上传到AMAZON服务器。现在我该怎么办?请问您有什么建议吗? - Gunjan Patel

0

@Bethoven 我已经在使用远程钩子了。但是,在将其转换为缩略图视图,然后上传到Amazon S3的情况下,它不会起作用。为了使其工作,我需要一些类似于 req.files.image 的 express 语法。 - Robins Gupta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接