2022年1月現在、GraphQLでファイルをアップロードするための仕様は公式には定義されていません。
なのでクライアント側とサーバー側でファイルをどのように扱うかを自分で決めてそれに沿った実装を行う必要があります。
非公式ではありますがGraphQLでのファイルアップロードのよく参照される仕様があるのでこちらに沿って実装を行うとライブラリの恩恵等が得られるのでおすすめです。
この仕様に沿って実装されたライブラリ郡もまとめられています。
JavaScriptクライアント側の実装について
GraphQLのjsクライアントライブラリとしてよく使われるのはApolloとRelayです。
Apolloはgraphql-multipart-request-specに則ってファイルアップロードを行うライブラリが提供されているのでこちらを利用するとスムーズに実装ができます。
対してRelayにはライブラリは用意されていない(僕が探した限り)ので自前で実装する必要があります。
ですが仕様を理解すれば実装はそれほど難しくありません。
↓のページではRelayクライアントを使いgraphql-multipart-request-specに則って実装する方法を紹介しています。
サーバー側の実装について
僕はサーバー側をRuby on Railsとgraphql-ruby gemを使い実装しました。
graphql-ruby gemでgraphql-multipart-request-specに則ってファイルアップロードを実装するためのライブラリとしてapollo_upload_server-ruby gemがあります。
これは名前にapolloとついていますがApollo専用というわけではなく、graphql-multipart-request-specに準拠したリクエストを処理するためのライブラリなので、クライアントがRelayでもspecに準拠したリクエストであれば問題なく使えます。
このgemはRailsのMiddlewareとして動作し、Gemfileに記載すれば自動的に使用されます。
あとはgraphql-ruby gemのscaler typeとして以下のようなモジュールを用意し、これをファイルアップロードのargumentの型に指定すれば動きます。
# frozen_string_literal: true
module ScalarTypes
class File < BaseScalar
class << self
def coerce_input(input_value, _context)
return nil unless input_value
ActionDispatch::Http::UploadedFile.new(
filename: input_value.original_filename,
type: input_value.content_type,
tempfile: input_value.tempfile,
head: input_value.headers,
)
end
end
end
end