美文网首页
Graphql文件上传

Graphql文件上传

作者: snow4web | 来源:发表于2019-03-21 11:31 被阅读0次
    apollo

    2019年用了Graphql作为web项目api开发后,前端编程效率有了质的提升。Graphql使得数据的查询,修改等操作变得极其灵活,但Graphql 对于文件上传的支持不是很好,于是笔者花了点时间整理了一个解决方案。

    Graphql Multipart Request 规范


    为了统一graphql上传文件服务端和客户端接口,好在Apollo社区提出了一份规范jaydenseric/graphql-multipart-request-spec: A spec for GraphQL multipart form requests (file uploads).

    该规范定义了文件上传的数据格式。

    文件上传定义为一个graphql的mutation 官方叫Operations。

    1. Operations 是一个Json对象,其中的files设为null。
    2. map: 也是一个Json对象定义了一次上传所有的文件,例如
    { "0": ["variables.files.0"], "1": ["variables.files.1"] }
    
    1. File fields: 是对应Operations中所有的文件。

    工作原理


    上传功能分为两部分服务端和客户端,分别按照规范实现接口。

    客户端:在客户端,把上传的文件翻译成一个Operations然后发送一个multipart 请求给服务端。

    服务端:服务端收到一个multipart请求,按照Operations的格式提取文件。

    例子


    首先定义服务端 graphql schema。

    const { ApolloServer, gql } = require('apollo-server');
    
    const typeDefs = gql`
      type File {
        filename: String!
        mimetype: String!
        encoding: String!
      }
      type Query {
        uploads: [File]
      }
      type Mutation {
        singleUpload(file: Upload!): File!
      }
    `;
    

    其中 Upload为一个Scalar Type 不做任何序列化的操作。

    const resolvers = {
      Query: {
        files: () => {
          // Return the record of files uploaded from your DB or API or filesystem.
        }
      },
      Mutation: {
        async singleUpload(parent, { file }) {
          const { stream, filename, mimetype, encoding } = await file;
    
          // 1. Validate file metadata.
    
          // 2. Stream file contents into cloud storage:
          // https://nodejs.org/api/stream.html
    
          // 3. Record the file upload in your DB.
          // const id = await recordFile( … )
    
          return { filename, mimetype, encoding };
        }
      },
    };
    

    以上为 resolver 部分的代码。

    客户端代码,需要按照apollo-upload-client(https://github.com/jaydenseric/apollo-upload-client) 这个包。

    
    const { ApolloClient } = require('apollo-client')
    const { InMemoryCache } = require('apollo-cache-inmemory')
    const { createUploadLink } = require('apollo-upload-client')
    
    const client = new ApolloClient({
      cache: new InMemoryCache(),
      link: createUploadLink()
    })
    
    import gql from 'graphql-tag'
    import { Mutation } from 'react-apollo'
    
    export const UPLOAD_FILE = gql`
      mutation uploadFile($file: Upload!) {
        uploadFile(file: $file) {
          filename
        }
      }
    `;
    
    const uploadOneFile = () => {
      return (   
        <Mutation mutation={UPLOAD_FILE}>
          {uploadFile => (
            <input
            type="file"
            required
            onChange={({ target: { validity, files: [file] } }) =>
              validity.valid && uploadFile({ variables: { file } });
            }
           />
          )}
        </Mutation>
      );
    };
    

    apollo client 需要通过createUploadLink来配置,当一个 input file 触发onChange时候,发送文件上传mutation。

    相关文章

      网友评论

          本文标题:Graphql文件上传

          本文链接:https://www.haomeiwen.com/subject/prnfvqtx.html