【问题标题】:Amplify S3 Image - 404 Not Found放大 S3 图像 - 404 未找到
【发布时间】:2021-08-02 05:18:23
【问题描述】:

我正在尝试访问已上传到我的 S3 存储桶的图像。我使用 Amplify CLI (amplify add storage) 创建了我的存储桶,并授予对我所有 cognito 组的访问权限。我还授予了我的 AuthRole AmazonS3FullAccess。我的存储桶也设置为允许所有公共访问。

我已经尝试了所有可以在网上找到的不同方法来访问此图像,而目前唯一可行的方法是将其向公众开放并直接使用图像 url。但即使我使用 Amplify 的工具访问图像的公共方法,我也会收到 404 错误。下面是我的代码,是不是我的 url 生成有问题?

资源:

import React, { Component} from 'react'
import Amplify, { Auth, Storage } from 'aws-amplify';
import { AmplifyS3Image} from "@aws-amplify/ui-react";
import { Card } from 'reactstrap';

// FYI, this all matches my aws-exports and matches what I see online in the console
Amplify.configure({
    Auth: {
        identityPoolId: 'us-east-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', //REQUIRED - Amazon Cognito Identity Pool ID
        region: 'us-east-1', // REQUIRED - Amazon Cognito Region
        userPoolId: 'us-east-1_XXXXXXXXX', //OPTIONAL - Amazon Cognito User Pool ID
        userPoolWebClientId: 'XXXXXXXXXXXXXXXXX', //OPTIONAL - Amazon Cognito Web Client ID
    },
    Storage: {
        AWSS3: {
            bucket: 'xxxxxxxxx-storage123456-prod', //REQUIRED -  Amazon S3 bucket name
            region: 'us-east-1', //OPTIONAL -  Amazon service region
        }
    }
});

class TestPage extends Component {
    constructor(props) {
        super(props);
        this.state = {  }
    };

    async componentDidMount() {
        const user = await Auth.currentAuthenticatedUser();
        const deviceKey = user.signInUserSession.accessToken.payload['device_key']
        console.log( deviceKey, user );

        const storageGetPicUrl = await Storage.get('test_public.png', {
            level: 'protected',
            bucket: 'xxxxxxxxx-storage123456-prod',
            region: 'us-east-1',
          });
        console.log(storageGetPicUrl);
        
        this.setState({
            user,
            deviceKey,
            profilePicImg: <img height="40px" src={'https://xxxxxxxxx-storage123456-prod.s3.amazonaws.com/test_public.png'} />,
            profilePicPrivate: <AmplifyS3Image imgKey={"test_default.png"} />,
            profilePicPublic: <AmplifyS3Image imgKey={"test_public.png"} />,
            profilePicPrivate2: <AmplifyS3Image imgKey={"test_default.png"} level="protected" identityId={deviceKey} />,
            profilePicPublic2: <AmplifyS3Image imgKey={"test_public.png"} level="protected" identityId={deviceKey} />,
            profilePicStorage: <img src={storageGetPicUrl} />,
          });
    };

    render() { 
        return ( 
            <table>
                <tbody>
                    <tr><td><Card>{this.state.profilePicImg}</Card></td></tr>
                    <tr><td><Card>{this.state.profilePicPrivate}</Card></td></tr>
                    <tr><td><Card>{this.state.profilePicPublic}</Card></td></tr>
                    <tr><td><Card>{this.state.profilePicPrivate2}</Card></td></tr>
                    <tr><td><Card>{this.state.profilePicPublic2}</Card></td></tr>
                    <tr><td><Card>{this.state.profilePicStorage}</Card></td></tr>
                </tbody>
            </table>
        );
    };
};
 
export default TestPage;

【问题讨论】:

  • 同样的问题,有更新吗?
  • 我没有时间做更多的工作,所以我一直公开所有内容。但是你的评论激起了一些动力,所以我绕道而行,努力去做!我相信我现在已经想通了,请给我几分钟的时间来起草并在此处发布解决方案。
  • @HoracioSolorio 我刚刚发布了我的解决方案 :)

标签: amazon-web-services amazon-s3 amazon-cognito


【解决方案1】:

好的,我知道了!有2个问题。一,AWS 存储要求您以某种方式组织存储桶中的文件夹结构以供访问。第二,我必须更新我的存储桶策略以指向我的 AuthRole。

  1. 当您配置存储桶时,Amplify CLI 将为您的 S3 存储桶设置访问权限,这样登录到您应用程序的每个人都可以访问“公共”文件夹中的内容。 'private' 用于用户特定的内容,'protected' 用于用户特定的内容,并且平台中的其他用户可以访问。 SOURCE
  2. 存储桶策略本身需要更新,以对您在网页登录中使用的 AuthRole 进行身份验证。对我来说,这是我的 Cognito 用户链接到的 AuthRole。 This link helped me set the Actions in my policy, but I think it's an old policy format.This link helped me with getting the policy right.

我的图片位于:public/test.png 在我的存储桶中。文件夹名称“public”是与下面存储调用中指定的级别相匹配的必要条件。我通过设置所有权限阻止公共访问来测试这一点。我在没有更改策略的情况下运行了我的代码,并且图像不会加载,因此它们肯定被阻止了。更新策略后,图片加载完美。

我的重要代码部分的简化版本:

import { Storage } from 'aws-amplify';

// image name should be relative to the public folder
// example: public/images/test.png => Storage.get('images/test.png' ...
const picUrl= await Storage.get('test.png', {
  level: 'public',
  bucket: 'bucket-name',
  region: 'us-east-1',
});
const img = <img width="40px" name="test" src={picUrl} alt="testImg" />

我的存储桶策略:

{
    "Version": "2012-10-17",
    "Id": "Policy1234",
    "Statement": [
        {
            "Sid": "AllowReadWriteObjects",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::the-rest-of-my-authrole-arn"
            },
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::bucket-name/*"
            ]
        }
    ]
}

【讨论】:

  • 感谢您的帮助我刚刚更改为公开级别,现在所有者和经过身份验证的管理员组用户可以看到图像感谢支持。
  • Public 没问题,但是如果你想保护你的图像免受万维网的影响,我上面的解决方案应该可以工作。我还发现在上传时总是必须编辑权限以使图像公开是很痛苦的。您还可以根据身份验证组名称等编辑策略以指向特定文件夹,以便不同的用户具有不同的访问权限。
猜你喜欢
  • 2019-01-25
  • 2020-10-15
  • 2016-09-13
  • 2021-08-11
  • 1970-01-01
  • 2020-04-05
  • 2018-02-25
  • 2021-03-18
  • 2020-09-20
相关资源
最近更新 更多