【问题标题】:Wrong Image orientation when uploading - Amazon S3上传时图像方向错误 - Amazon S3
【发布时间】:2018-01-14 17:28:40
【问题描述】:

我让用户使用 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: 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");
    }
    });
    });

我如何在前端显示图像。 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="small" src="<%= url2 %>">

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

【问题讨论】:

  • 看看this
  • @MathieudeLorimier 感谢您发送邮件。很有意思。我想我宁愿在后端而不是前端解决这个问题。有什么想法吗? :)
  • 我同意,@mostafazh 有一些很棒的建议。
  • 值得注意的是,ImageMagick(最新版本)解码 Exif 数据并将方向存储在“image->orientation”中。如果发生更改,我不相信它(还)将该值存储回 Exif 配置文件中。
  • @GlennRanders-Pehrson 非常感谢您让我知道这个 Glenn!关于如何处理多图像方面的任何想法? :)

标签: node.js image-processing file-upload amazon-s3 imagemagick


【解决方案1】:

问题是 iOS 设置了图像的 EXIF 元数据,导致了这种行为。您可以使用可以读取 EXIF 元数据并为您旋转图像的库。

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'; // 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!");
    });
});

您可以从here 找到一些具有不同 EXIF 旋转元数据的示例图像

转换为 AWS Lambda 函数

// 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);
                }
              });
            });
        }
    });
};

注意事项 此功能将旋转后的图像上传到同一个存储桶,但您可以轻松更改它。如果您刚开始使用 AWS Lambda,我建议您了解有关它的更多信息(https://www.youtube.com/watch?v=eOBq__h4OJ4https://www.youtube.com/watch?v=PEatXsXIkLc

确保您拥有正确的权限(读取和写入)、正确的函数触发器、正确的“处理程序”在创建函数时!确保也检查 CloudWatch 中的函数日志,使调试更容易。如果它开始超时,请增加函数超时并增加它的内存。

【讨论】:

  • 嘿@mostafazh 感谢您的出色回答!我的麻烦之一是用户一次上传多张图片。一次最多 25 个。在这两个示例中,它看起来像是在旋转一张图片:“fixed.jpg”和“IMG_0001.jpg”。这如何处理多张图片?非常感谢!!!
  • 您将需要为每张图片执行此操作。您还可以“花哨”并创建一个 AWS Lambda 函数,该函数将监听每个上传到 S3 的图像,并让 Lambda 函数自动旋转图像。 Lambda 的一个好处是它们可以并行执行,并使您的请求保持轻量(只需将文件上传到 S3)。有关 AWS Lambda 的更多信息docs.aws.amazon.com/lambda/latest/dg/lambda-introduction.html
  • 谢谢你把它寄过来!你有没有机会更新你的答案,展示一个如何做到这一点的例子? :)
  • 另一个想法,考虑到节点的事件驱动行为,@AndrewLeonardi 你也可以让服务器返回对请求的成功上传响应。无论如何,服务器将继续处理图像?
  • 非常感谢您的所有帮助!惊人的答案。
猜你喜欢
  • 2019-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-17
  • 2018-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多