乐趣区

关于javascript:从React应用中使用GraphQL上传文件

React 前端的文件上传能够通过 Apollo Upload Client 来实现。

GraphQL 使咱们开发者可能在前端利用和 REST API 之间实现一个弱小而灵便的形象层。作为一个 3 个月前才接触到 GraphQL 的实习生,我浏览了许多文章、博客文章和 GraphQL 社区成员筹备的指南,理解如何构建 GraphQL 服务并将其连贯到 React 利用。但这些资源都没有提到应用 GraphQL 能够上传文件。

文件上传也能够这样说吗?兴许 …

当我授命治理和构建一个新的性能,包含应用 GraphQL 实现文件上传时,我意识到尽管这个性能蕴含在 Apollo Server 2.0 中,但大多数对于这个性能的资源都被安排在不同的资源库中,而且指南也脱漏了重要的步骤。

我从浏览官网博客文章开始钻研这个性能,并虔诚地依照它的步骤进行钻研,但可怜的是,这是我进入神秘谬误之海的入口,只因为博客文章不残缺。我花了近一周的工夫,在 github 仓库中跳转 GraphQL 文件上传性能,以找出我的代码有什么问题。

因而,我决定收集这篇指南,展现通过应用 GraphQL 渐变实现根本的文件上传性能 GraphQL 服务器和 React 客户端的必要步骤。另外,谈谈我对 GraphQL 这个性能的教训,以及为什么作为一个公司咱们决定抉择不同的办法。

在上面的局部中,本指南将带您通过必要的步骤来创立一个 GraphQL 服务器,该服务器能够解决从 React 应用程序与 Apollo Client 发送的文件上传渐变。GraphQL 服务器要有 2 种不同的性能;将文件保留到文件系统中 将其流进 S3 bucket 中

Basic Architecture

所有部件的示意图,更多细节请查看

(https://github.com/epalaz/gra…)。

在本指南中,咱们的零碎将由以下局部组成。
1.带有 Apollo 客户端包的 React 利用。
2.应用 Apollo 服务器包的 GraphQL 服务器。

咱们的 GraphQL 服务器将有能力将上传的文件保留到文件系统中,并将接管到的数据流流进 AWS 上的 S3 Bucket。为此,咱们将有 2 个查问:singleUploadsingleUploadStream

Step 1: Preparing GraphQL Server

Setup

要应用 apollo-server 库创立一个 GraphQL 服务器,最简略的办法是依照它的官网指南,但我还是会在这里列出所需步骤。
首先创立一个目录并安装包。

    $ mkdir your_dir_name  
    $ cd your_dir_name  
    $ yarn init --yes  
    $ yarn add apollo-server graphql graphql-upload  
    $ yarn add aws-sdk

这组命令应该安装包和创立。下一步就是开始定义出类型定义和解析器。

类型定义和渐变解析器

渐变的类型定义和填充物查问

咱们定义了 2 种不同的渐变。singleUpload渐变用于上传文件并将其保留到文件系统的一个目录中,而 singleUploadStream 则用于流式传输到 S3 bucket。这些渐变采纳 Upload 标量类型,在 Apollo Server 2.0 中是默认的,所以它的解析是由 apollo 服务器本人实现的。Apollo 服务器将多局部申请模式映射到这个 Upload 标量,并为文件生成一个 承诺 。这两个渐变都会返回 文件 类型,该类型由 文件名、mimetype 编码 字段组成,尽管这并不合乎现实生活中的日程安排,但返回文件的正确字段示意文件正确上传至 GraphQL 服务器。

SingleUpload 和 singleUploadStream 渐变的解析器

在这些文件上传解析器中,一个要害的细节是文件参数返回的承诺。为了可能读取文件流,咱们应该期待承诺被解析。在这个例子中,两个渐变解析器应用了不同的办法。singleUpload通过应用 then() 返回承诺,并将解析后的流保留到文件系统中。另一方面,singleUploadStream应用 await 期待承诺解析,通过应用文件流将文件上传到 S3。这些解析器的另一个区别是,在解析器函数外面应用 await 须要将其定义为 async,而singleUpload 解析器能够放弃同步。

注:旧的例子能够显示文件具备 filed stream,而不是 createReadStream 函数。最新的变更请查看 graphql-upload repository。变动的 PR](https://github.com/jaydenseri…。

配置服务器和 AWS SDK

这个 server.js 文件蕴含了在 localhost 的 4000 端口上启动 Apollo 服务器并配置 AWS JavaScript SDK 的代码。(更多细节请参考文档)。应用类型定义和渐变解析器创立 ApolloServer 实例应该足以解决文件上传,以便保留在文件系统中并上传到 S3。如果你须要进一步帮忙在 AWS 上创立 S3 Buckets,请参考这个链接。

    const {ApolloServer, gql} = require('apollo-server');
    const fs = require('fs')
    const typeDefs = gql`  
      type File {
        filename: String!
        mimetype: String!
        encoding: String!
      }
      type Query {_ : Boolean}
      type Mutation {singleUpload(file: Upload): File!,    
      }
    `;
    const resolvers = {
      Mutation: {singleUpload: (parent, args) => {
          return args.file.then(file => {const {createReadStream, filename, mimetype} = file
            const fileStream = createReadStream()
            fileStream.pipe(fs.createWriteStream(`./${filename}`))
            return file;
          });
        },
      },
    };
    const server = new ApolloServer({typeDefs, resolvers});
    server.listen().then(({ url}) => {console.log(`\`????  Server ready at ${url}`);
    });
    });

您能够通过键入以下内容测试 GraphQL 服务器

$ cd your_project_dir  
$ node server.js

到你的控制台。这应该启动服务器的端口 4000 的 localhost。在这之后键入 localhost:4000 到你的浏览器,你应该可能看到 Playground 页面上,你能够发送查问和渐变到服务器进行测试,也能够看到主动生成的文件的根底上。

Apollo Server 游乐场截图显示定义的渐变和查问。

当初,你能够验证你的渐变和查问是否被服务器辨认,你曾经筹备好从你的 React 利用中向服务器发送 graphql 申请。

只管 graphiql 自身的 ide 不反对,然而能够应用 altair 测试上传文件和查看后果。

Step 2: Creating the React Application

为了轻松地创立咱们的 react 利用和它的模板代码,咱们将使用户 create-react-app 工具由 Facebook 开发。

$ yarn create react-app your-app-name。
$ yarn add apollo-client apollo-upload-client react-apollo graphql-tag

这条命令应该创立一个给定名称的 react 利用目录,并主动生成模板代码,开始开发咱们的利用。你能够通过输出以下命令来测试这个命令是否胜利

$ 纱线开始

这时应该在 localhost:3000 端口上启动开发服务器,并进行实时更新。

由 create-react-app 创立的利用示例。

如果你能看到这个屏幕,阐明你的我的项目曾经设置胜利,你能够开始编辑这个模板来上传你的文件。

配置 Apollo 客户端并为渐变筹备 Schemas

        import React from 'react';
        import logo from './logo.svg';
        import './App.css';
        import {InMemoryCache} from 'apollo-cache-inmemory'
        import {createUploadLink} from 'apollo-upload-client'
        import {ApolloClient} from "apollo-client"
        import {ApolloProvider, Mutation} from "react-apollo"
        import gql from "graphql-tag"
        const apolloCache = new InMemoryCache()
        const uploadLink = createUploadLink({
          uri: 'http://localhost:4000', // Apollo Server is served from port 4000
          headers: {"keep-alive": "true"}
        })
        const client = new ApolloClient({
          cache: apolloCache,
          link: uploadLink
        })
        const UPLOAD_FILE = gql`
          mutation SingleUpload($file: Upload) {singleUpload(file: $file) {
              filename
              mimetype
              encoding
            }
          }
        `;
        function App() {
          return (
            <div className="App">
              <ApolloProvider client={client}>
                <header className="App-header">
                    <img src={logo} className="App-logo" alt="logo" />
                    <h2>Save Local</h2>
                        <Mutation mutation={UPLOAD_FILE}>
                            {(singleUpload, { data, loading}) => {console.log(data)
                                return (<form onSubmit={() => {console.log("Submitted")}} encType={'multipart/form-data'}>
                                            <input name={'document'} type={'file'} onChange={({target: { files}}) => {const file = files[0]
                                                file && singleUpload({variables: { file: file} })
                                            }}/>{loading && <p>Loading.....</p>}</form>)}
                            }
                        </Mutation>
                </header>
              </ApolloProvider>
            </div>
          );
        }
        export default App;

这段代码创立了一个根本的 UI,有 1 个表单,一个是 singleUpload,在这个例子中,onChange 事件被用来启动文件上传渐变函数,但你也能够抉择用你所抉择的事件来启动它。做文件上传 onChange 能够让你在文件被选中后立刻上传。另一个细节是将表单元素的encTypemultipart/form-data。查看这个链接来浏览对于 GraphQL 多局部申请标准的更多细节。在设置了这些组件的渲染函数后,你的 UI 应该看起来有点相似于这样。

React 利用实例的 UI

第三步:测试和上传文件

** 测试文件系统保留
在测试之前,请确保服务器和 react 应用程序都已启动并运行。如果没有,请依照步骤 1 和 2 启动它们。让咱们尝试用singleUpload** 渐变上传一个文件,看看它是否保留在服务器文件系统中。

如果你查看控制台,你应该能够看到 GraphQL 服务器返回的上传文件信息。这意味着咱们的上传胜利了,剩下的事件就是验证服务器是否将文件保留到文件系统中。

Aaand voila,”no-image.png “ 文件胜利上传并保留到文件系统。
能够通过 chrome devtools 查看具体的提交内容。看到这个内容,再去浏览 graphql 文件提交标准,会容易不少。并且,能够参照此标准,应用 Vanillajs 来编写客户端代码,而不是非要应用 React 不可。

退出移动版