ファイルのアップロードは突然変異のようです。多くの場合、他のデータが付随しています。しかし、これは大きなバイナリ BLOB であるため、GraphQL がどのように処理できるかはわかりません。ファイルのアップロードを Relay で構築されたアプリにどのように統合しますか?
5 に答える
Rails固有のMarc-Andre Girouxのブログからの調査結果を共有しているだけなので、より一般的なものにして、@Nickから提供された回答の詳細を提供します。
2 つの部分があります。
- クライアント側の Javascript コード
- サーバー側のサーバー固有のコード
クライアント側の Javascript コード
クライアント側のコードは、さらに 2 つの部分で構成されています。
Relay.Mutation (UploadFileMutation) を拡張したアップロード ファイルへのミューテーション
// The actual mutation class UploadFileMutation extends Relay.Mutation { getFiles() { return { file: this.props.file, }; } // ... Rest of your mutation }
ファイルを選択するための UI をレンダリングするための React コンポーネント (FileUploader) を含むコンポーネントであり、アップロードを行うためにミューテーションを呼び出します。
// A react component to upload a file class FileUploader extends React.Component { onSubmit() { const name = this.refs.name.value; const file = this.refs.fileInput.files.item(0); Relay.Store.update( new UploadFileMutation({ name: name, file: file, }) ); } // ... Rest of React component, e.g., render() }
サーバー側のサーバー固有のコード
サーバー側のコードも 2 つの部分で構成されています。
- アップロードされたファイルを MIME マルチパート形式で取得し、それを GraphQL スキーマで定義された Mutation に渡す処理を行う部分。NodeJS と Rails の例を提供します。これは、他のサーバーのソリューションを導き出すのに役立ちます。
NodeJS Express サーバーの場合 ( @Nickが指摘したExpress -graqphlテスト ケースから抽出):
import multer from 'multer';
var app = express();
var graphqlHTTP = require('express-graphql');
// Multer provides multipart form data parsing.
var storage = multer.memoryStorage();
app.use(urlString(), multer({ storage }).single('file'));
// Providing the request, which contains the file MIME
// multipart as `rootValue` to enable it to
// be accessible from within Schema resolve functions.
app.use(urlString(), graphqlHTTP(req => {
return {
schema: YourMutationSchema,
rootValue: { request: req }
};
}));
同様に、RubyOnRails などの非 JS サーバーの場合:
def create
query_string = params[:query]
query_variables = ensure_hash(params[:variables]) || {}
query = GraphQL::Query.new(
YourSchema,
query_string,
variables: query_variables,
# Shove the file MIME multipart into context to make it
# accessible by GraphQL Schema Mutation resolve methods
context: { file: request.params[:file] }
)
- Mutation は、渡されたファイル MIME マルチパートを取得できます
Javascript GraphQL スキーマの場合:
var YourMutationSchema = new GraphQLSchema({
query: new GraphQLObjectType({
// ... QueryType Schema
}),
mutation: new GraphQLObjectType({
name: 'MutationRoot',
fields: {
uploadFile: {
type: UploadedFileType,
resolve(rootValue) {
// Access file MIME multipart using
const _file = rootValue.request.file;
// ... Do something with file
}
}
}
})
});
Rails GraphQL スキーマの場合:
AddFileMutation = GraphQL::Relay::Mutation.define do
name "AddFile"
input_field :name, !types.String
# ... Add your standard mutation schema stuff here
resolve -> (args, ctx) {
# Retrieve the file MIME multipart
file = ctx[:file]
raise StandardError.new("Expected a file") unless file
# ... Do something with file
}
end
他の回答に加えて、Relay Modern では、クライアントからファイルを送信する方法に小さな変更がありました。ミューテーションに を含めてファイルをコンストラクターに渡す代わりにgetFiles
、次のようなものを使用できます。
UploadFileMutation.js
// @flow
import { commitMutation, graphql } from 'react-relay';
import type { Environment } from 'react-relay';
import type { UploadFileInput, UploadFileMutationResponse } from './__generated__/uploadFileMutation.graphql';
const mutation = graphql`
mutation UploadFileMutation( $input: UploadFileInput! ) {
UploadFile(input: $input) {
error
file {
url
}
}
}
`;
const getOptimisticResponse = (file: File | Blob) => ({
UploadFile: {
error: null,
file: {
url: file.uri,
},
},
});
function commit(
environment: Environment,
{ fileName }: UploadFileInput,
onCompleted: (data: UploadFileMutationResponse) => void,
onError: () => void,
uploadables,
) {
return commitMutation(environment, {
mutation,
variables: {
input: { fileName },
},
optimisticResponse: getOptimisticResponse(uploadables.fileToUpload),
onCompleted,
onError,
uploadables,
});
}
export default { commit };
コンポーネントでの使用:
const uploadables = {
fileToUpload: file, // file is the value of an input field for example
};
UploadFileMutation.commit(
this.props.relay.environment,
{ fileName },
onCompleted,
onError,
uploadables
);
ドキュメントには言及されていないため、uploadables
構成オプションは隠されていますが、ここで見つけることができます: commitRelayModernMutation.js#L32