17

ファイルのアップロードは突然変異のようです。多くの場合、他のデータが付随しています。しかし、これは大きなバイナリ BLOB であるため、GraphQL がどのように処理できるかはわかりません。ファイルのアップロードを Relay で構築されたアプリにどのように統合しますか?

4

5 に答える 5

4

Rails固有のMarc-Andre Girouxのブログからの調査結果を共有しているだけなので、より一般的なものにして、@Nickから提供された回答の詳細を提供します。

2 つの部分があります。

  • クライアント側の Javascript コード
  • サーバー側のサーバー固有のコード

クライアント側の Javascript コード

クライアント側のコードは、さらに 2 つの部分で構成されています。

  1. Relay.Mutation (UploadFileMutation) を拡張したアップロード ファイルへのミューテーション

    // The actual mutation
    class UploadFileMutation extends Relay.Mutation {
      getFiles() {
        return {
          file: this.props.file,
        };
      }
    
      // ... Rest of your mutation
    }
    
  2. ファイルを選択するための 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 つの部分で構成されています。

  1. アップロードされたファイルを 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] }
     )
  1. 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
于 2016-03-13T10:20:57.623 に答える
1

他の回答に加えて、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

于 2017-07-26T15:00:26.507 に答える