【问题标题】:Saving base64 string to Amazon S3将 base64 字符串保存到 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?

感谢您的帮助!

【问题讨论】:

  • 订阅,我也需要这个

标签: amazon-s3 base64 react-native


【解决方案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 字符串加载的图像不能正常工作,因为我在测试时手动上传的一些图像看起来很好。
      猜你喜欢
      • 2016-12-03
      • 2015-12-05
      • 2021-03-13
      • 1970-01-01
      • 2013-06-04
      • 2014-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多