如何使用 AWS AppSync 将文件上传到 AWS S3
Posted
技术标签:
【中文标题】如何使用 AWS AppSync 将文件上传到 AWS S3【英文标题】:How to upload file to AWS S3 using AWS AppSync 【发布时间】:2018-07-07 19:10:32 【问题描述】:在 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
`
然而,即使在我实施了这些更改之后,文件也没有上传...
【问题讨论】:
您是否拥有 S3 存储桶的 AWS 凭证?您使用的 AppSync 授权方案是什么? 我尝试使用不同的方案。我应该使用哪一个? 您需要 AWS IAM 凭证,我建议为此使用 Cognito Identity。如果您希望在应用程序中轻松执行此操作,请查看 AWS Amplify:github.com/aws/aws-amplify 谢谢@Richard!我将重温本教程。我希望来自 aws amazon 的人在将它们发布到网上之前检查这些教程。我必须进行大量调整才能使上述教程正常工作。 你能告诉我们有哪些调整吗?或者发布您的工作代码? 【参考方案1】:只是为了加入讨论。对于移动客户端,放大(或者如果从 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,但我没有检查。
【讨论】:
【参考方案2】:在这个“正常工作”(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(当所有凭据都设置正确时 - 我们稍后会谈到),但它没有解决如何获取 S3Object
背部。这就是需要附加到本地数据源的字段级解析器的地方。本质上,您需要在 AppSync 中创建一个本地数据源,并使用以下请求和响应解析器将其连接到架构中模型的 file
字段:
## Request Resolver ##
"version": "2017-02-28",
"payload":
## Response Resolver ##
$util.toJson($util.dynamodb.fromS3ObjectJson($context.source.file))
这个解析器只是告诉 AppSync 我们想要为模型的 file
字段获取存储在 DynamoDB 中的 JSON 字符串,并将其解析为 S3Object
- 这样,当您查询模型时,而不是返回存储在 file
字段中的字符串,您将获得一个包含 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(),
);
假设所有这些事情都准备就绪,通过 AppSync 的 S3 上传和下载应该可以工作。
【讨论】:
我使用的是 react-native 而不是 reactJS。当我使用 imagepicker 之类的东西时,如何从 react native 加载图像复杂对象到 AppSync? docs.aws.amazon.com/appsync/latest/devguide/… 此处的示例仅提供带有 的示例,但没有使用 imagepickers 的示例。我尝试只提供本地 uri,但这不起作用 - 创建了文档;但是,没有上传 s3 对象。 我还没有研究这是否可行,但你不能使用隐藏的 和图像选择器并让图像选择器调用一个方法来更新隐藏的 合适的文件对象?以上是关于如何使用 AWS AppSync 将文件上传到 AWS S3的主要内容,如果未能解决你的问题,请参考以下文章
无法将大型 graphql 模式上传到 aws appsync
在 React 中使用 AWS Amplify Appsync 上传图像
在将 aws cdk 与 appsync 一起使用时,如何将突变添加到 graphql 架构并防止部署失败?
使用 AWS AppSync 将项目附加到 DynamoDB