簡體   English   中英

如何使用GraphQL將圖像上傳到AWS S3?

[英]How to upload an image to AWS S3 using GraphQL?

我正在上傳一個base64字符串,但GraphQL被掛起了。 如果我將字符串切片少於50,000個字符就可以了。 在50,000個字符之后,graphQL永遠不會使其成為解析函數,但不會產生錯誤。 在較小的字符串上,它工作得很好。

const file = e.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
  const imageArray = reader.result;
  this.context.fetch('/graphql', {
    body: JSON.stringify({
      query: `mutation s3Upload($img: String!) {
        s3Upload(file: $img) {
          logo,
        }
      }`,
      variables: {
        img: imageArray,
      },
    }),
  }).then(response => response.json())
  .then(({ data }) => {
    console.log(data);
  });
}

const s3Upload = {
    type: S3Type,
    args: {
      file: { type: new NonNull(StringType) },
    },
    resolve: (root, args, { user }) => upload(root, args, user),
};

const S3Type = new ObjectType({
  name: 'S3',
  fields: {
    logo: { type: StringType },
  },
});

這里正確的方法是使用AWS AppSync通過復雜類型執行實際的S3上傳 - 您在此處說明的內容更像是您嘗試將base64編碼的圖像作為字符串保存到字段中,我只能假設為DynamoDB表條目。 但是,要使其工作,您需要修改變異,使file字段不是String! ,但是一個S3ObjectInput

在“正常工作”(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 ,該file是類型為S3ObjectInput的模型字段。 以這種方式設置請求解析器會處理將文件上傳到S3(當所有憑據都設置正確時 - 我們稍后會觸及它),但它沒有解決如何恢復S3Object 這是附加到本地數據源的字段級解析器變得必要的地方。 實質上,您需要在AppSync中創建本地數據源,並使用以下請求和響應解析器將其連接到模式中的模型file字段:

## Request Resolver ##
{
    "version": "2017-02-28",
    "payload": {}
}

## Response Resolver ##
$util.toJson($util.dynamodb.fromS3ObjectJson($context.source.file))

此解析器只是告訴AppSync我們想要將存儲在DynamoDB中的JSON字符串作為模型的file字段並將其解析為S3Object - 這樣,當您對模型進行查詢時,而不是返回存儲的字符串在file字段中,您將獲得一個包含bucketregionkey屬性的對象,您可以使用這些對象構建URL以訪問S3對象(直接通過S3或使用CDN - 這實際上取決於您的配置)。

確保你有為復雜對象設置的憑據,但是(告訴你我會回到這里)。 我將使用React示例來說明這一點 - 在定義AppSync參數(端點,身份驗證等)時,需要定義一個名為complexObjectCredentials的附加屬性,以告訴客戶端用於處理S3上載的AWS憑據。 ,例如:

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

假設所有這些都已到位,那么通過AppSync進行S3上傳和下載應該可行。

AWS AppSync( https://aws.amazon.com/appsync/ )為此提供了稱為“復雜對象”的功能,您可以在其中獲得S3對象和輸入的類型:

type S3Object {
    bucket: String!
    key: String!
    region: String!
}

input S3ObjectInput {
    bucket: String!
    key: String!
    region: String!
    localUri: String
    mimeType: String
}

然后你可以做這樣的事情來定義這個對象作為另一種類型的一部分:

type UserProfile {
    id: ID!
    name: String
    file: S3Object
}

然后指定一個突變來添加它:

type Mutation {
    addUser(id: ID! name: String file: S3ObjectInput): UserProfile!
}

您的客戶端操作需要指定適當的存儲桶,密鑰(帶有文件擴展名),區域等。

更多信息: https//docs.aws.amazon.com/appsync/latest/devguide/building-a-client-app-react.html#complex-objects

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM