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

时间:2018-01-29 06:12:48

标签: amazon-s3 aws-appsync

在AWS AppSync文档中关注this docs/tutorial

它声明:

  

使用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 个答案:

答案 0 :(得分:18)

在“正常工作”(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,该对象是类型为S3ObjectInput的模型字段。以这种方式设置请求解析器会处理将文件上传到S3(当所有凭据都设置正确时 - 我们稍后会触及它),但它没有解决如何获取{{1 }} 背部。这是附加到本地数据源的字段级解析器变得必要的地方。实际上,您需要在AppSync中创建一个本地数据源,并使用以下请求和响应解析器将其连接到模式中的模型S3Object字段:

file

这个解析器只是告诉AppSync我们想要为模型的## Request Resolver ## { "version": "2017-02-28", "payload": {} } ## Response Resolver ## $util.toJson($util.dynamodb.fromS3ObjectJson($context.source.file)) 字段获取存储在DynamoDB中的JSON字符串并将其解析为file - 这样,当你这样做时查询模型,而不是返回存储在S3Object字段中的字符串,您将获得一个包含filebucketregion属性的对象,您可以使用它们构建一个访问S3对象的URL(直接通过S3或使用CDN - 这实际上取决于您的配置)。

确保您为复杂对象设置了凭据,但是(告诉您我会回到此处)。我将使用React示例来说明这一点 - 在定义AppSync参数(端点,身份验证等)时,需要定义一个名为key的附加属性,以告诉客户端要使用的AWS凭据处理S3上传,例如:

complexObjectCredentials

假设所有这些都已到位,通过AppSync进行S3上传和下载应该有效。

答案 1 :(得分:0)

只需添加到讨论中即可。对于移动客户端,amplify(或从aws控制台执行)会将突变调用封装到一个对象中。如果封装存在,则客户端不会自动上传。因此,您可以直接在aws控制台中修改变异调用,以便在调用参数中上载 file: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,但我没有检查。