graphqlでファイルをアップロードする
最近graphqlを触り始めました.
書いてて多分ぶち当たる案件にファイルのアップロードをどうするのかという問題があります.
この件についてこちらの記事が参考になります.
オチから書くと今回はbase64で実装しました.
記事中やGoogleで検索してると出てくるapollo-upload-server/clientが使いやすそうで良いのですが今回の実行環境がFirebase Functionsということがありそのままでは素直に動いてくれませんでした.
というのもapollo-upload-server/clientは以下で仕様が説明されている通りファイルをmultipartで送信します.
Firebase functionsではユーザーが使用しているexpressの前にGoogle側のexpressがいるらしくこいつがRequestを先に読み出してしまうようです.
そのため内部で使用されているbusboyがRequestを正常にパースすることが出来ず結果として
1Missing multipart field ‘operations’
とエラーが返ってきてアップロードすることができません.
multipart自体は以下の記事の説明にある通りGoogle Functionsのページには説明がありましたが上手く組み込めなかったので諦めました.
これについては
https://github.com/jaydenseric/apollo-upload-server/issues/19
https://github.com/jaydenseric/apollo-upload-server/issues/21
でも取り上げられていますが自分の技術力では解決出来なかったので誰か上手く行った方がいれば教えて欲しいです.
apollo-upload-server/client自体は以下のようなコードで動きます(多分
シンプルで良いですね.
server
1...
2import { GraphQLUpload } from "apollo-upload-server";
3import { apolloUploadExpress } from "apollo-upload-server"
4
5const schema = new GraphQLSchema({
6 mutation: new GraphQLObjectType({
7 name: "Mutation",
8 fields: {
9 uploadImage: {
10 type: GraphQLBool,
11 args: {
12 image: {type: GraphQLUpload},
13 },
14 resolve: async (_, args) => {
15 return await uploadImage(args);
16 }
17 },
18 }
19 })
20});
21const app = express();
22...
23app.use("/graphql", apolloUploadExpress());
clinet
1import HttpLink from "apollo-link-http";
2import fetch from "node-fetch";
3import ApolloClient from "apollo-client";
4import gql from "graphql-tag";
5import { createUploadLink } from 'apollo-upload-client'
6import { InMemoryCache } from 'apollo-cache-inmemory'
7import { ApolloLink } from 'apollo-link';
8
9const client = new ApolloClient({
10 cache: new InMemoryCache(),
11 link: createUploadLink({uri: "/path/to/graphql"}),
12 fetch: fetch,
13});
14
15document.getElementById("mutate").addEventListener("change", ((event) => {
16 const file = event.target.files[0];
17 client.mutate({
18 mutation: gql`
19 mutation uploadImageFile($file: Upload!) {
20 uploadImage(image: $file){
21 created
22 }
23 }
24 `,
25 variables: {file},
26 })
27 .then(data => console.log(data))
28 .catch(error => console.error(error));
29}));