将 base64 字符串保存到 Amazon S3
Posted
技术标签:
【中文标题】将 base64 字符串保存到 Amazon S3【英文标题】:Saving base64 string to Amazon S3 【发布时间】:2016-08-24 14:04:39 【问题描述】:我正在开发一个 React Native 应用程序,我试图从用户的相机胶卷中获取图像,将它们转换为 base64 字符串并将它们存储到 Amazon S3 以供以后使用。
在这篇博文之后,我可以获取用户的相机胶卷并将图像转换为 base64: react-native-creating-a-custom-module-to-upload-camera-roll-images
然后,我将 base64 字符串图像数据发送到一个简单的 Express 服务器,该服务器已设置为将数据发布到我的 Amazon S3 存储桶。
// Only getting first img in camera roll for testing purposes
CameraRoll.getPhotos(first: 1).then((data) =>
for (let i = 0; i < data.edges.length; i++)
NativeModules.ReadImageData.readImage(data.edges[i].node.image.uri, (imageBase64) =>
// Does the string have to be encoded?
// const encodeBase64data = encodeURIComponent(imageBase64);
const obj =
method: 'POST',
headers:
'Accept': 'application/json',
'Content-Type': 'application/json',
,
body: JSON.stringify(
'img': imageBase64
)
fetch('http://localhost:3000/saveImg', obj)
.then((res) =>
console.log(JSON.parse(res._bodyInit));
)
)
在这种情况下,我的 imageBase64
变量是一个相当大的字符串,如下所示:/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAAA...abX+Yub/API3zf8A7G2Z/wDqdiD/AExyf/kT5R/2Kst/9QqB0x6H6GuBbr1R6D2foz+ZT/gof/yep8bf934f/wDqC6PX96+Cn/JruFf+6z/6t8UfwP4wf8nM4n9Mq/8AVbRPjOv1I/OAoA//2Q==
...
还有几个字符。
我正在将此 base64 字符串发送到我的快递服务器并发布数据:
app.post('/saveImg', function(req, res)
// this will be moved once testing is complete
var s3Bucket = new AWS.S3( params: Bucket: '[my_bucket_name]' );
// Do I need to append this string to the image?
var baseImg = 'data:image/png;base64,' + req.body.img;
var data =
Key: test_img,
Body: req.body.img,
ContentEncoding: 'base64',
ContentType: 'image/png'
;
s3Bucket.putObject(data, function(err, data)
if (err)
console.log(err);
console.log('Error uploading data: ', data);
else
res.send(data);
console.log('successfully uploaded the image!');
);
// res.send(base64data)
);
我成功地将数据发送到 Amazon S3 并在存储桶中查看了我的图像文件,但是当我尝试访问链接以查看实际图像本身或将其拉入我的 React Native 应用程序时,我什么也得不到。
ie 如果我在 Amazon S3 中访问上面的 test_img
的 URL,我会得到:
https://s3.amazonaws.com/my_bucket_name/test_img
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>BCE6E07705CF61B0</RequestId>
<HostId>
aF2l+ucPPHRog1QaaXjEahZePF0A9ixKR0OTzlogWFHYXHUMUeOf2uP7D/wtn7hu3bLWG8ulKO0=
</HostId>
</Error>
我已经手动将图像上传到同一个存储桶,它们的链接看起来很好,而且我还可以将它们拉到我的 React Native 应用程序中查看。
我的问题是在获取 base64 字符串数据并将其发送到我的 Express 服务器以保存到我的存储桶之间我做错了什么? 是否必须对 base64 字符串进行编码? 在将 base64 字符串发送到 Express 之前,是否需要将其转换为 Blob?
感谢您的帮助!
【问题讨论】:
订阅,我也需要这个 【参考方案1】:我刚刚遇到了同样的问题。在上传到 S3 之前,您必须将 base64 字符串转换为 Blob。
This answer 解释了如何进行这种转换。使用node-fetch,以下是在您的示例中集成的方法:
require('node-fetch')
app.post('/saveImg', function(req, res)
// this will be moved once testing is complete
var s3Bucket = new AWS.S3( params: Bucket: '[my_bucket_name]' );
var imageUri = 'data:image/png;base64,' + req.body.img;
fetch(imageUri)
.then(function(res) return res.blob() )
.then(function(image)
var data =
Key: test_img,
Body: image,
ContentEncoding: 'base64',
ContentType: 'image/png'
;
s3Bucket.putObject(data, function(err, data)
if (err)
console.log(err);
console.log('Error uploading data: ', data);
else
res.send(data);
console.log('successfully uploaded the image!');
);
)
);
完成后,您可以在 S3 上预览上传的图片或将其拉入您的应用。
【讨论】:
【参考方案2】:向您的存储桶添加存储桶策略将解决该问题。
【讨论】:
【参考方案3】:这是一个权限问题,与 ReactNative 和 Base64 编码无关。
您遇到 “AccessDenied”-错误,这意味着该图像不公开。只有当您使用正确的权限(甚至是特定文件,我将在下面解释)配置您的存储桶时,您才会收到没有签名 URL 的图像内容。
要调查这是否是根本原因,您可以尝试在 s3 控制台中公开图像。只需转到your s3-bucket 并右键单击图像文件:
在上下文菜单中为您列出了两个有趣的项目:“公开”和“公开”。
如果您选择“打开”,您将获得文件的“签名 url”,这意味着图像的纯 url 将附加特定参数,以使该文件在一段时间内公开可用:
您也可以尝试“公开”并重新加载您的图片网址,看看它现在是否可供您使用。
1.方法,桶范围:
一种解决方案是为整个存储桶创建一个 IAM-Policy 以公开其中的每个对象:
"Version": "2008-10-17",
"Statement": [
"Sid": "AllowPublicRead",
"Effect": "Allow",
"Principal":
"AWS": "*"
,
"Action": [ "s3:GetObject" ],
"Resource": [ "arn:aws:s3:::YOUR_BUCKET_NAME/*" ]
]
因此,在 AWS 控制台中转到您的存储桶,单击存储桶,然后在右侧窗格中打开“权限”。您可以创建与上述类似的新策略。
2。第二种解决方案,对象特定
另一种方法是将ACL-specific headers 添加到 putObject-Method:
'ACL' => 'public-read'
我不知道你的后端 SDK,但我猜是这样的:
var data =
Key: test_img,
Body: req.body.img,
ContentEncoding: 'base64',
ContentType: 'image/png',
ACL: 'public-read',
;
我刚刚在此处添加了 ACL 特定行。 根据 SDK 的不同,可能需要使用普通的 aws-headers“x-amz-acl:public-read”而不是“ACL:public-read”。两个都试试。
【讨论】:
不幸的是,这个解决方案对我不起作用。我为我的存储桶添加了 IAM-Policy,当我尝试从它们各自的 url 加载从相机胶卷中保存的图像时,我只看到页面左上方出现一个小的空白白色方块。我确保我的存储桶中的图像也是公开的,但我仍然遇到同样的问题。只有我从相机胶卷作为 base64 字符串加载的图像不能正常工作,因为我在测试时手动上传的一些图像看起来很好。以上是关于将 base64 字符串保存到 Amazon S3的主要内容,如果未能解决你的问题,请参考以下文章
Amazon S3 .NET:上传 base64 图像数据?
使用 Amazon s3 boto 库,如何获取已保存密钥的 URL?
尽管存储桶是公共的,但 Amazon S3 base64 图像不适用于 og:image 标签