如何有效地允许用户查看 Amazon S3 内容?

How to efficiently allow for users to view Amazon S3 content?

我目前正在使用 React-Native(前端)和 Flask/MongoDB(后端)创建一个基本应用程序。我计划使用 AWS S3 作为便宜的云存储来存储所有要上传和查看的图像和视频。我目前的想法(这可能完全不可行)是当用户上传内容时,它将通过我的 Flask API 然后到 S3 存储。当用户想要查看内容时,我不确定这里的攻击计划是什么。我应该使用我的 Flask API 作为代理,还是有一种方法可以直接将 link 发送到 S3 上的内容(这将避免通过我的 API 的额外流量)?

我对使用 AWS 还很陌生,如果 post 已经有人在讨论这个话题,请告诉我,我非常乐意删除这个重复的话题。我似乎找不到任何东西。

Should I use my Flask API as a proxy, or is there a way to simply send a link to the content directly on S3 (which would avoid the extra traffic through my API)?

如果内容是 public,您只需提供一个 URL 直接指向 S3 存储桶上的文件。

如果内容是私有的,您可以在后端为您要授予访问权限的文件生成 presigned url。此 URL 应该在短时间内有效(例如:15/30 分钟)。如果它变得不可用,您可以重新生成它。

此外,您可以生成预签名的URL,可用于直接从前端上传到S3 存储桶。如果您不希望上传流量通过后端或者您想要更快的上传速度,这可能是一个选项。

有一个APIboto3,试试看吧

没那么难,我也做过类似的东西,会post这里码一下。

我按照@Ervin 说的做了。

  1. 前端要求后端生成凭据
  2. 后端向前端发送凭据
  3. 前端上传文件到S3
  4. 前端警告后端它已经完成。
  5. 后端验证是否一切正常。
  6. 后台会创建一个link下载,你有很多安全选项。

项目 6) 的示例生成预签名 url 以下载内容。

    bucket = app.config.get('BOTO3_BUCKET', None)
    client = boto_flask.clients.get('s3')

    params = {}
    params['Bucket'] = bucket
    params['Key'] = attachment_model.s3_filename
    params['ResponseContentDisposition'] = 'attachment; filename={0}'.format(attachment_model.filename)
    if attachment_model.mimetype is not None:
        params['ResponseContentType'] = attachment_model.mimetype

    url = client.generate_presigned_url('get_object', ExpiresIn=3600, Params=params)

项目 2 的示例)后端将为 post 您在 S3 上的文件创建预签名凭据,将 s3_credentials 发送到前端

    acl_permission = 'private' if private_attachment else 'public-read'
    condition = [{'acl': acl_permission},
                 ["starts-with", "$key", '{0}/'.format(folder_name)],
                 {'Content-Type': mimetype }]

    bucket = app.config.get('BOTO3_BUCKET', None)
    fields = {"acl": acl_permission, 'Bucket': bucket, 'Content-Type': mimetype}
    client = boto_flask.clients.get('s3')
    s3_credentials = client.generate_presigned_post(bucket, s3_filename, Fields=fields, Conditions=condition, ExpiresIn=3600)

第 5 项的示例) 这是后端如何检查 S3 上的文件是否正常的示例。

    bucket = app.config.get('BOTO3_BUCKET', None)
    client = boto_flask.clients.get('s3')
    response = client.head_object(Bucket=bucket, Key=s3_filename)
    if response is None:
        return None, None

    md5 = response.get('ETag').replace('"', '')
    size = response.get('ContentLength')

这是一个示例,前端将如何请求凭据、将文件上传到 S3 并通知后端已完成。 我试图删除很多特定代码。

//frontend asking backend to create credentials, frontend will send some file metadata
AttachmentService.createPostUrl(payload).then((responseCredentials) => {
    let form = new FormData();
    Object.keys(responseCredentials.s3.fields).forEach(key => {
      form.append(key, responseCredentials.s3.fields[key]);
    });
    form.append("file", file);
    let payload = {
        data: form,
        url: responseCredentials.s3.url
    }
    
    //Frontend will send file to S3
    axios.post(payload.url, payload.data).then((res) => {
      return Promise.resolve(true);
    }).then((result) => {

        //when it is done, frontend informs backend
        AttachmentService.uploadSuccess(...).then((refreshCase) => {
            //Success 
        });
    });
});