上传时错误的图像方向 - Amazon S3 [英] Wrong Image orientation when uploading - Amazon S3

查看:257
本文介绍了上传时错误的图像方向 - Amazon S3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我让用户使用Multer-S3将 多个图像 直接上传到Amazon-S3,然后通过循环在前端显示这些图像。所有的作品完美。然而,当通过手机上传图片(在iPhone或Android上拍摄的图片)时,手机的方向是正确的,但在桌面上没有正确的方向。主要问题。



这是由于我相信图像的EXIF数据。



看起来像ImageMagick或Kraken JS https://kraken.io/docs/storage-s3 可能是解决这个问题的一种方法,但是对于我来说,我无法弄清楚如何实现上传和显示下面显示的图像。



如何更改我的代码以自动定位图片?注意:它必须适用于多个图像。

感谢您的帮助!



如何让用户一次将多个图片直接上传到Amazon-S3:

  aws。 config.update({
secretAccessKey:'AccessKey',
accessKeyId:'KeyID',
region:'us-east-2'
});

var s3 = new aws.S3();

var storage = multerS3({
limits:{files:25},
s3:s3,
bucket:'files',
key:函数(req,file,cb){
var fileExtension = file.originalname.split(。)[1];
var path =uploads /+ req.user._id + Date。 now()+。+ fileExtension;
cb(null,path);
},
})


var upload = multer {storage:storage})。any(images,25);

router.post(/,middleware.isLoggedIn,function(req,res,next){

upload(req,res,function(err){
$ if(err){
console.log(err);
res.redirect('/')
}




Listing.findById(req.params.id,function(err,foundListings){

var allimages = []

if(typeof req.files! ==undefined){
for(var i = 0; i< req.files.length; i ++){
allimages.push(req.files [i] .key);


var currentimages = allimages;

var newListings = {currentimages:currentimages}
//移除了其他模型方面
列表。 create(newListings,function(err,newlyCreated){
if(err){
console.log(err);
} else {

res.redirect / listing);
}
});
});

我如何显示图像在前端。 Listings.currentimages是一个包含所有图像链接的数组。

  app.locals.awspath =https://s3.us-east-2.amazonaws.com/myfiles/ ; 

// awspath 是我的Amazon-S3路径的文件路径

 < div id ='allimages'> 
<%for(var i = 0; i< listings.currentimages.length; i ++){%>
< div class ='smallerImages'>

<%var url2 = awspath + listings.currentimages [i]%>
< img class =smallsrc =<%= url2%>>

< / div>
<%}%>
< / div>


解决方案

问题在于iOS设置了图片的EXIF元数据导致此行为。您可以使用可以读取EXIF元数据并为您旋转图像的库。


$ b jpeg-autorotate https://github.com/johansatge/jpeg-autorotate )是一个简单的 有很好的文档(你应该检查出来)。



示例



  var jo = require('jpeg-autorotate'); 
var fs = require('fs');

// var options = {quality:85};
var options = {};
var path ='/tmp/Portrait_8.jpg'; //你也可以使用Buffer
jo.rotate(path,options,function(error,buffer,orientation){
if(error){
console.log('An error发生在旋转文件时:'+ error.message);
return;
}
console.log('Orientation was:'+ orientation);

/上传缓冲区到s3,保存到磁盘或更多...
fs.writeFile(/ tmp / output.jpg,buffer,function(err){
if(err){
return console.log(err);
}

console.log(The file was saved!);
});
});

您可以从 here



转换为AWS Lambda函数



  //将此文件命名为index.js并将其压缩为+ node_modules,然后上载到AWS Lambda 

console.log('加载函数');
var aws = require('aws-sdk');
var s3 = new aws.S3({apiVersion:'2006-03-01'});
var jo = require('jpeg-autorotate');

//旋转给定一个缓冲区的图像
var autorotateImage = function(data,callback){
jo.rotate(data,{},function(error,buffer,orientation) ){
if(error){
console.log('旋转文件时发生错误:'+ error.message);
callback(error,null);
}其他{
console.log('方向是:'+ orientation);
callback(null,buffer);
}
});
};
$ b $ // // AWS Lambda在每次将新文件上传到s3
时运行此操作exports.handler = function(event,context,callback){
console.log('Received event: ',JSON.stringify(event,null,2));
//从事件中获取对象并显示其内容类型
var bucket = event.Records [0] .s3.bucket.name;
var key = event.Records [0] .s3.object.key;
s3.getObject({Bucket:bucket,Key:key},function(err,data){
if(err){
console.log(Error getting object+ key + from bucket+ bucket +
。确保它们存在,并且你的bucket和这个函数在同一个区域。);
callback(Error getting file:+ err,null);
} else {
//记录内容类型,应该是图片
console.log('CONTENT TYPE:',data.ContentType);
//旋转图片
autorotateImage(data.Body,function(error,image){
if(error){
callback(Error rotate image:+ error,null);
}

const params = {
桶:桶,
键:'rotate /'+键,
正文:image
};
/ /上传新图片,注意不要将其上传到w再次触发功能!
s3.putObject(params,function(err,data){
if(error){
callback(Error uploadloading rotate image:+ error,null);
}
console.log(在S3上成功上传图片,data);
//调用AWS Lambda的回调,函数成功!!!
callback(null,data);
}
});
});
}
});
};

注意此功能会将旋转后的图片上传到同一个存储分区,轻易改变这一点。如果您刚开始使用AWS Lambda,则建议您详细了解它( https:// https://www.youtube .com / watch?v = PEatXsXIkLc

确保您拥有正确的权限(读写),正确的函数触发器,正确的Handler在创建函数的时候!确保在CloudWatch中检出功能日志,使调试更容易。如果开始超时,请增加功能超时并增加内存。


I'm letting users upload multiple images directly to Amazon-S3 using Multer-S3 and then displaying those images on the front end via a loop. All works perfectly.

However when the images are uploaded via mobile (image taken on an iPhone or Android) the orientation is correct on mobile but does NOT have correct orientation on desktops. Major problem.

This is due to the images EXIF data I believe.

Seems like ImageMagick or Kraken JS https://kraken.io/docs/storage-s3 might be a way to solve it but for the life of me I cannot figure out how to implement either with the way I'm uploading and showing images shown below.

How would I change my code below to auto-orient the images? Note: It must work for multiple images.

Thanks for any help!

Heres's how I'm letting users upload multiple images at a time directly to Amazon-S3:

aws.config.update({
    secretAccessKey: 'AccessKey',
    accessKeyId: 'KeyID',
    region: 'us-east-2'
});

var s3 = new aws.S3();

    var storage =  multerS3({
        limits : { files: 25 },
        s3: s3,
        bucket: 'files',
        key: function (req, file, cb) {
            var fileExtension = file.originalname.split(".")[1];
            var path = "uploads/" + req.user._id + Date.now() + "." + fileExtension;
            cb(null, path); 
        },
    })


var upload = multer({storage: storage}).any("images", 25);

router.post("/", middleware.isLoggedIn, function(req, res, next){

        upload(req,res,function(err) {
        if(err) {
        console.log(err);
        res.redirect('/')
        }




Listings.findById(req.params.id, function(err, foundListings){

    var allimages = []

            if(typeof req.files !== "undefined") {
            for(var i = 0; i < req.files.length; i++) {
                allimages.push(req.files[i].key);
            }
            }
 var currentimages = allimages;

 var newListings = {currentimages:currentimages}
 //Removed the other Model aspects
    Listings.create(newListings, function(err, newlyCreated){
        if(err){
            console.log(err);
        } else {

 res.redirect("/listings");
    }
    });
    });

How I'm displaying the images on the front end. Listings.currentimages is an array containing all image links.

app.locals.awspath = "https://s3.us-east-2.amazonaws.com/myfiles/";

// awspath is the file path to my Amazon-S3 path

<div id='allimages'>
<% for(var i = 0; i < listings.currentimages.length; i++ ) { %>
<div class='smallerImages'>

<%  var url2 = awspath + listings.currentimages[i] %>
<img class="small" src="<%= url2 %>">

</div>
<% } %>
</div>

解决方案

The problem is that iOS sets the image's EXIF metadata which causes this behavior. You can use a library that can read the EXIF metadata and rotate the image for you.

jpeg-autorotate (https://github.com/johansatge/jpeg-autorotate) is a very simple lib and has very nice documentation (you should check it out).

Example

var jo = require('jpeg-autorotate');
var fs = require('fs');

// var options = {quality: 85};
var options = {};
var path = '/tmp/Portrait_8.jpg'; // You can use a Buffer, too
jo.rotate(path, options, function(error, buffer, orientation) {
    if (error) {
        console.log('An error occurred when rotating the file: ' + error.message);
        return;
    }
    console.log('Orientation was: ' + orientation);

    // upload the buffer to s3, save to disk or more ...
    fs.writeFile("/tmp/output.jpg", buffer, function(err) {
        if(err) {
            return console.log(err);
        }

        console.log("The file was saved!");
    });
});

You can find some sample images with different EXIF rotation metadata from here

Converted as an AWS Lambda Function

// Name this file index.js and zip it + the node_modules then upload to AWS Lambda

console.log('Loading function');
var aws = require('aws-sdk');
var s3 = new aws.S3({apiVersion: '2006-03-01'});
var jo = require('jpeg-autorotate');

// Rotate an image given a buffer
var autorotateImage = function(data, callback) {
  jo.rotate(data, {}, function(error, buffer, orientation) {
      if (error) {
          console.log('An error occurred when rotating the file: ' + error.message);
          callback(error, null);
      } else {
        console.log('Orientation was: ' + orientation);
        callback(null, buffer);
      }
  });
};

// AWS Lambda runs this on every new file upload to s3
exports.handler = function(event, context, callback) {
    console.log('Received event:', JSON.stringify(event, null, 2));
    // Get the object from the event and show its content type
    var bucket = event.Records[0].s3.bucket.name;
    var key = event.Records[0].s3.object.key;
    s3.getObject({Bucket: bucket, Key: key}, function(err, data) {
        if (err) {
            console.log("Error getting object " + key + " from bucket " + bucket +
                ". Make sure they exist and your bucket is in the same region as this function.");
            callback("Error getting file: " + err, null);
        } else {
            // log the content type, should be an image
            console.log('CONTENT TYPE:', data.ContentType);
            // rotate the image
            autorotateImage(data.Body, function(error, image) {
              if (error) {
                callback("Error rotating image: " + error, null);
              }

              const params = {
                Bucket: bucket,
                  Key: 'rotated/' + key,
                  Body: image
              };
              // Upload new image, careful not to upload it in a path that will trigger the function again!
              s3.putObject(params, function (err, data) {
                if (error) {
                    callback("Error uploading rotated image: " + error, null);
                } else {
                  console.log("Successfully uploaded image on S3", data);
                  // call AWS Lambda's callback, function was successful!!!
                  callback(null, data);
                }
              });
            });
        }
    });
};

Notes This function upload the rotated images to the same bucket but you can easily change that. If you are just starting with AWS Lambda, I'd suggest you learn more about it (https://www.youtube.com/watch?v=eOBq__h4OJ4, https://www.youtube.com/watch?v=PEatXsXIkLc)

Make sure you've the right permissions (read and write), correct function trigger, correct "Handler" when creating the function! Make sure to checkout the function logs in CloudWatch too, makes debugging a lot easier. If it starts timing out, increase the function timeout and increase it's memory.

这篇关于上传时错误的图像方向 - Amazon S3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆