使用用户信息从 React Native 上传 Amazon s3 存储桶中的项目

Posted

技术标签:

【中文标题】使用用户信息从 React Native 上传 Amazon s3 存储桶中的项目【英文标题】:Uploading item in Amazon s3 bucket from React Native with user's info 【发布时间】:2021-06-30 06:50:56 【问题描述】:

我正在使用带有 AWS amplify 的 React Native 在 AWS S3 上上传图像以进行移动应用程序开发。许多用户使用我的应用程序。

    我希望每当任何用户通过移动应用在 S3 上上传图片时,我希望与该图片一起获取用户的 ID。这样以后我就可以识别 S3 上的图像,哪个图像属于哪个用户。我怎样才能做到这一点?

    我正在使用 AWS Auth Cognito 进行用户注册/登录。我了解到,每当用户(第一次)在 AWS cognito 中注册时,用户都会在池中获得一个唯一 ID。每当用户上传图片时,我可以使用此用户 ID 与图片一起传递吗?

基本上,我想要某种形式的功能,以便我可以追踪到在 S3 上上传图像的用户。这是因为图像上传到 S3 后,我稍后想处理此图像并将结果 ONLY 发送回图像的用户。

【问题讨论】:

【参考方案1】:

您可以将数据存储在类似于以下结构的 S3 中:

users/
   123userId/
       image1.jpeg
       image2.jpeg
   anotherUserId456/
       image1.png
       image2.png

然后,如果您需要来自给定用户的所有文件,您可以在 S3 lambda 中使用 ListObjects API - docs here

// for lambda function
    const AWS = require('aws-sdk');  
    const s3 = new AWS.S3();

    const objects = await s3.listObjectsV2(
      Bucket: 'STRING_VALUE', /* required */
      Delimiter: 'STRING_VALUE',
      EncodingType: url,
      ExpectedBucketOwner: 'STRING_VALUE',
      Marker: 'STRING_VALUE',
      MaxKeys: 'NUMBER_VALUE',
      Prefix: 'STRING_VALUE',
      RequestPayer: requester
    ).promise()

objects.forEach(item => 
      console.log(item
));

或者,如果您使用 S3 Lambda 触发器,您可以从 S3 lambda 中接收到的事件中的“key”/文件名解析 userId(如果您使用上述结构)。

 
          "key": "public/users/e1e0858f-2ea1-90f892b68e0c/item.jpg",
          "size": 269582,
          "eTag": "db8aafcca5786b62966073f59152de9d",
          "sequencer": "006068DC0B344DA9E9"
 

另一种选择是将“userId”写入将上传到 S3 的文件的元数据中。 您可以从 Cognito 当前登录的用户传递“sub”属性,因此在 S3 Lambda 触发器函数中,您将从元数据中获取 userId。

import Auth from "@aws-amplify/auth";

const user = await Auth.currentUserInfo();
const userId = user.attributes.sub;
return userId;



// use userId from Cognito and put in into custom metadata
import Storage from "aws-amplify";

const userId = "userIdHere"
const filename = "filename" // or use uuid()
const ref = `public/users/@userId/$filename`

const response = await Storage.put(ref, blob, 
        contentType: "image/jpeg",
        metadata: userId: userId,
      );

AWS Amplify 可以自动完成以上所有操作(创建文件夹结构等),如果您不需要任何特殊结构,文件的存储方式 = docs here。 您只需要使用“级别”属性配置存储(“全局”或每个操作)。

Storage.configure( level: 'private' );
await Storage.put(ref, blob, 
        contentType: "image/jpeg",
        metadata: userId: userId,
      );


//or set up level only for given action
const ref= "userCollection"
await Storage.put(ref, blob, 
        contentType: "image/jpeg",
        metadata: userId: userId,
        level: "private"
      );

因此,例如,如果您使用级别“private”,文件“124.jpeg”将存储在 S3 中 “私人/us-east-1:6419087f-d13e-4581-b72e-7a7b32d7c7c1/userCollection/124.jpeg”

但是,如您所见,“us-east-1:6419087f-d13e-4581-b72e-7a7b32d7c7c1”看起来与 Cognito 中的“sub”不同(“sub”属性不包含区域)。

相关的discussion is here,也有一些解决方法,但基本上你需要决定如何在你的项目中自己管理用户标识(如果你在任何地方都使用“sub”作为userId,或者你将使用另一个ID - 我认为它被称为身份ID,并将其视为用户ID)。

PS:如果您使用 React Native,我想您会使用推送通知从后端发送更新 - 如果是这种情况,我正在做类似的事情(“审核控制”) - 所以我添加了另一个 Lambda 函数,Cognito 的确认后 Lambda,它在 DynamoDB 中使用 Cognito 的“子”属性的 ID 创建用户。 然后用户可以从移动设备保存推送通知所需的令牌,因此当 AWS Rekognition 完成对用户上传的图像的检测后,我查询 DynamoDB 并使用 SNS 将通知发送给最终用户。

【讨论】:

以上是关于使用用户信息从 React Native 上传 Amazon s3 存储桶中的项目的主要内容,如果未能解决你的问题,请参考以下文章

React-Native个人信息界面

react-native 图片选取与上传

Cloudinary API 图像上传的正确 React Native“文件”?

将视频 URI 从 React-Native Picker 上传到 AWS S3 服务器

React native - 您上传的 APK 没有使用上传证书签名

004-React-Native--多图选择上传