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をクリックすると複数ファイルの選択も可能。