首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >您将如何在React-Relay应用程序中进行文件上传?

您将如何在React-Relay应用程序中进行文件上传?
EN

Stack Overflow用户
提问于 2015-10-11 07:51:07
回答 5查看 8.7K关注 0票数 17

文件上传看起来像是一种变异。它通常伴随着其他数据。但这是一个很大的二进制blob,所以我不确定GraphQL如何处理它。如何将文件上传集成到使用Relay构建的应用程序中?

EN

回答 5

Stack Overflow用户

发布于 2016-02-24 02:36:27

首先,您需要在您的前端组件中编写Relay更新。如下所示:

代码语言:javascript
复制
onDrop: function(files) {
  files.forEach((file)=> {
    Relay.Store.commitUpdate(
      new AddImageMutation({
        file,
        images: this.props.User,
      }),
      {onSuccess, onFailure}
    );
  });
},

然后在前端实现突变:

代码语言:javascript
复制
class AddImageMutation extends Relay.Mutation {
   static fragments = {
     images: () => Relay.QL`
       fragment on User {
         id,
       }`,
     };

   getMutation() {
     return Relay.QL`mutation{ introduceImage }`;
   }

   getFiles() {
     return {
       file: this.props.file,
     };
   }

   getVariables() {
     return {
       imageName: this.props.file.name,
     };
   }

   getFatQuery() {
     return Relay.QL`
       fragment on IntroduceImagePayload {
         User {
           images(first: 30) {
             edges {
               node {
                 id,
               }
             }
           }
         },
         newImageEdge,
       }
     `;
   }

   getConfigs() {
     return [{
       type: 'RANGE_ADD',
       parentName: 'User',
       parentID: this.props.images.id,
       connectionName: 'images',
       edgeName: 'newImageEdge',
       rangeBehaviors: {
         '': 'prepend',
       },
     }];
   }
 }

最后,在服务器/模式上实现处理程序。

代码语言:javascript
复制
const imageMutation = Relay.mutationWithClientMutationId({
  name: 'IntroduceImage',
  inputFields: {
    imageName: {
      type: new GraphQL.GraphQLNonNull(GraphQL.GraphQLString),
    },
  },
  outputFields: {
    newImageEdge: {
      type: ImageEdge,
      resolve: (payload, args, options) => {
        const file = options.rootValue.request.file;
        //write the image to you disk
        return uploadFile(file.buffer, filePath, filename)
        .then(() => {
          /* Find the offset for new edge*/
          return Promise.all(
            [(new myImages()).getAll(),
              (new myImages()).getById(payload.insertId)])
          .spread((allImages, newImage) => {
            const newImageStr = JSON.stringify(newImage);
            /* If edge is in list return index */
            const offset = allImages.reduce((pre, ele, idx) => {
              if (JSON.stringify(ele) === newImageStr) {
                return idx;
              }
              return pre;
            }, -1);

            return {
              cursor: offset !== -1 ? Relay.offsetToCursor(offset) : null,
              node: newImage,
            };
          });
        });
      },
    },
    User: {
      type: UserType,
      resolve: () => (new myImages()).getAll(),
    },
  },
  mutateAndGetPayload: (input) => {
    //break the names to array.
    let imageName = input.imageName.substring(0, input.imageName.lastIndexOf('.'));
    const mimeType = input.imageName.substring(input.imageName.lastIndexOf('.'));
    //wirte the image to database
    return (new myImages())
    .add(imageName)
    .then(id => {
    //prepare to wirte disk
      return {
        insertId: id,
        imgNmae: imageName,
      };
    });
  },
});

上面的所有代码你可以在我的repo https://github.com/bfwg/relay-gallery中找到,还有一个实时的演示https://fanjin.io

票数 10
EN

Stack Overflow用户

发布于 2015-10-11 19:00:39

我找到an explanation in the docs了。您可以子类化Relay.Mutation并实现getFiles函数。

此外,express-graphql在其测试用例中提供了an example,用于说明如何在服务器端处理此问题。

票数 5
EN

Stack Overflow用户

发布于 2016-03-13 18:20:58

我只是从他的blog分享Marc-Andre Giroux的发现,这是Rails特定的,所以我将尝试让它更通用,并提供@Nick提供的答案的详细信息。

分为两个部分:

  • 客户端Javascript code
  • Server-side服务器特定代码

客户端Javascript代码

客户端代码进一步由两部分组成:

  1. 上传文件的变体,它扩展了Relay.Mutation (UploadFileMutation)

//实际的突变类UploadFileMutation扩展了Relay.Mutation { getFiles() {getFiles{this.props.file: this.props.file,};} // ...

  • 包含React组件(FileUploader)的组件,用于呈现用于选择文件的UI,并调用该变体进行上载

//上传文件类FileUploader的react组件扩展React.Component { onSubmit() { const name = this.refs.name.value;const file = this.refs.fileInput.files.item(0);Relay.Store.update( UploadFileMutation({ name: name,file: file,}) );} // ...React组件的其余部分,例如render() }

服务器端特定于服务器的代码

服务器端代码也由两部分组成:

  1. 处理检索MIME多部分格式的上载文件并将其传递给GraphQL架构中定义的变体的部分。我们提供了NodeJS和Rails示例,可以帮助您为其他服务器派生解决方案。

对于Nick Express服务器(从@Nick指出的express-graqphl测试用例中提取):

代码语言:javascript
复制
    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 }
      };
    }));

类似地,对于非JS服务器,例如RubyOnRails:

代码语言:javascript
复制
    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. 变种可以检索传递给它的文件MIME

对于Javascript GraphQL架构:

代码语言:javascript
复制
    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方案:

代码语言:javascript
复制
    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
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33060182

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档