我让用户使用 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>
最佳答案
问题是 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 旋转元数据的示例图像
// 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__h4OJ4、https://www.youtube.com/watch?v=PEatXsXIkLc)
确保您拥有正确的权限(读取和写入)、正确的函数触发器、正确的“处理程序”在创建函数时!确保也检查 CloudWatch 中的函数日志,使调试更容易。如果它开始超时,请增加函数超时并增加它的内存。
关于node.js - 上传时图像方向错误 - Amazon S3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45546375/
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file
我克隆了一个rails仓库,我现在正尝试捆绑安装背景:OSXElCapitanruby2.2.3p173(2015-08-18修订版51636)[x86_64-darwin15]rails-v在您的Gemfile中列出的或native可用的任何gem源中找不到gem'pg(>=0)ruby'。运行bundleinstall以安装缺少的gem。bundleinstallFetchinggemmetadatafromhttps://rubygems.org/............Fetchingversionmetadatafromhttps://rubygems.org/...Fe
在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee
我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie
我有两个Rails模型,即Invoice和Invoice_details。一个Invoice_details属于Invoice,一个Invoice有多个Invoice_details。我无法使用accepts_nested_attributes_forinInvoice通过Invoice模型保存Invoice_details。我收到以下错误:(0.2ms)BEGIN(0.2ms)ROLLBACKCompleted422UnprocessableEntityin25ms(ActiveRecord:4.0ms)ActiveRecord::RecordInvalid(Validationfa
这个问题在这里已经有了答案:Arraysmisbehaving(1个回答)关闭6年前。是否应该这样,即我误解了,还是错误?a=Array.new(3,Array.new(3))a[1].fill('g')=>[["g","g","g"],["g","g","g"],["g","g","g"]]它不应该导致:=>[[nil,nil,nil],["g","g","g"],[nil,nil,nil]]