知識のリンク集

技術系アウトプット

GolangでGraphQLのクエリに添付したファイルをS3にアップロードする

GraphQLでファイルデータをアップロード

GraphQLサーバーには gqlgen を利用。
gqlgenが提供する型の1つである `Upload` を使う。

scalar Upload
https://gqlgen.com/reference/scalars/

@graphql.schema

type Mutation {
  uploadFile(file: Upload): String
}

goで処理を受け取る際の引数(resolver)の型には*graphql.Uploadを指定

func (r *mutationResolver) UploadFile(ctx context.Context, file *graphql.Upload) (*string, error) {
  // ...
}

Uploadの中身は下記のとおり

type Upload struct {
	File        io.Reader
	Filename    string
	Size        int64
	ContentType string
}
S3にアップロード

S3にアップロードするために aws-sdk-go が提供するs3managerを利用。
https://aws.amazon.com/jp/sdk-for-go/

バケット名とオブジェクトキー、アップロードするファイルをio.Reader型で渡す。
Upload.Fileをそのまま渡せる。

bucketName := "xxx-bucket"
objectKey := "xxx-key"

uploader := s3manager.NewUploader(sess)
_, err = uploader.Upload(&s3manager.UploadInput{
    Bucket: aws.String(bucketName),
    Key:    aws.String(objectKey),
    Body:   file,
})
テスト

いつもはgqlgenが提供してくれるclientを使ってクエリを叩いてインテグレーションテストを行っていたのだがfileを正しく渡す方法がわからなくて断念した。

c := client.New(handler.GraphQL(graphql.NewExecutableSchema(graphql.Config{})))

targetFilePath := "./sample.txt"
file, err := os.Open(targetFilePath)
query := fmt.Sprintf(`mutation uploadFile {
    uploadFile(file: {file:%+v, fileName:"%s", size: %d, contenttype:"%s"}) 
}`, file, "fileName", 5, "contentType")

c.Post(query, &resp)

解決策としてはファイルのアップロードに関してはaltairを使って手動テストすることにした。
https://altair.sirmuel.design/altair.sirmuel.design


左下のファイルを選択でFinderからファイルを選択できる。
枠線のAdd Filesをクリックすると複数ファイルの選択も可能。

f:id:yuri_iOS:20200624000041p:plain