代码之家  ›  专栏  ›  技术社区  ›  SaidAkh

如何使用AWS AppSync将文件上载到AWS S3

  •  23
  • SaidAkh  · 技术社区  · 7 年前

    下列的 this docs/tutorial 在AWS AppSync文档中。

    它指出:

    使用AWS AppSync,您可以将其建模为GraphQL类型。如果您的任何突变都有一个带有bucket、key、region、mimeType和localUri字段的变量,SDK将为您将文件上载到Amazon S3。

    但是,我无法将文件上载到s3存储桶。我理解该教程缺少很多细节。更具体地说,教程没有说 NewPostMutation.js 需要更改。

    我用以下方式进行了更改:

    import gql from 'graphql-tag';
    
    export default gql`
    mutation AddPostMutation($author: String!, $title: String!, $url: String!, $content: String!, $file: S3ObjectInput ) {
        addPost(
            author: $author
            title: $title
            url: $url
            content: $content
            file: $file
        ){
            __typename
            id
            author
            title
            url
            content
            version
        }
    }
    `
    

    然而,即使在我实施了这些更改之后,文件也没有上传。。。

    2 回复  |  直到 7 年前
        1
  •  29
  •   hatboyzero    7 年前

    引擎盖下有一些活动部件,您需要确保在“正常工作”(TM)之前安装到位。首先,您需要确保为GraphQL模式中定义的S3对象具有适当的输入和类型

    enum Visibility {
        public
        private
    }
    
    input S3ObjectInput {
        bucket: String!
        region: String!
        localUri: String
        visibility: Visibility
        key: String
        mimeType: String
    }
    
    type S3Object {
        bucket: String!
        region: String!
        key: String!
    }
    

    这个 S3ObjectInput 当然,类型是在上载新文件时使用的,可以通过创建或更新嵌入所述S3对象元数据的模型。可以通过以下方式在突变的请求解析器中进行处理:

    {
        "version": "2017-02-28",
        "operation": "PutItem",
        "key": {
            "id": $util.dynamodb.toDynamoDBJson($ctx.args.input.id),
        },
    
        #set( $attribs = $util.dynamodb.toMapValues($ctx.args.input) )
        #set( $file = $ctx.args.input.file )
        #set( $attribs.file = $util.dynamodb.toS3Object($file.key, $file.bucket, $file.region, $file.version) )
    
        "attributeValues": $util.toJson($attribs)
    }
    

    这是假设S3文件对象是附加到DynamoDB数据源的模型的子字段。请注意,调用 $utils.dynamodb.toS3Object() 设置复杂的S3对象 file ,它是模型的字段,类型为 S3目标输入 . 以这种方式设置请求解析器将处理文件上传到S3的过程(当所有凭据都设置正确时-我们稍后再讨论),但它没有解决如何获取 S3Object 返回这就是需要连接到本地数据源的字段级解析器的地方。本质上,您需要在AppSync中创建一个本地数据源,并将其连接到模型的 文件 具有以下请求和响应解析程序的架构中的字段:

    ## Request Resolver ##
    {
        "version": "2017-02-28",
        "payload": {}
    }
    
    ## Response Resolver ##
    $util.toJson($util.dynamodb.fromS3ObjectJson($context.source.file))
    

    这个解析器只是告诉AppSync,我们希望将存储在DynamoDB中的JSON字符串用于 文件 字段并将其解析为 S3对象 -这样,当您查询模型时,而不是返回存储在 文件 字段,则得到一个包含 bucket , region key 可用于构建URL以访问S3对象的属性(直接通过S3或使用CDN,这取决于您的配置)。

    但是,一定要确保为复杂对象设置了凭据(告诉过你我会继续讨论这个问题)。我将使用React示例来说明这一点-在定义AppSync参数(端点、身份验证等)时,还有一个名为 complexObjectCredentials 需要定义它来告诉客户端使用什么AWS凭据来处理S3上载,例如:

    const client = new AWSAppSyncClient({
        url: AppSync.graphqlEndpoint,
        region: AppSync.region,
        auth: {
            type: AUTH_TYPE.AWS_IAM,
            credentials: () => Auth.currentCredentials()
        },
        complexObjectsCredentials: () => Auth.currentCredentials(),
    });
    

    假设所有这些都已就绪,S3通过AppSync上传和下载应该可以工作。

        2
  •  2
  •   Bruce    6 年前

    只是为了增加讨论的内容。对于移动客户端,amplify(或者如果从aws控制台执行)将把变异调用封装到对象中。如果存在封装,客户端将不会自动上载。因此,您可以在aws控制台中直接修改突变调用,以便上传 文件:S3ObjectInput 在调用参数中。这是我在文档之后最后一次测试(2018年12月)时发生的。

    您将更改此调用结构:

     type Mutation {
            createRoom(
            id: ID!,
            name: String!,
            file: S3ObjectInput,
            roomTourId: ID
        ): Room
    }
    

    而不是自动生成的调用,如:

    type Mutation {
        createRoom(input: CreateRoomInput!): Room
    }
    input CreateRoomInput {
        id: ID
        name: String!
        file: S3ObjectInput
    }
    

    一旦你做出这一改变,如果你按照@hatboyzero的描述去做,iOS和Android都会很乐意上传你的内容。

    [编辑]我做了一些研究,应该在2.7.3中已经解决了这个问题 https://github.com/awslabs/aws-mobile-appsync-sdk-android/issues/11 . 他们很可能是针对iOS的,但我没有检查。