1

以下是如何在GRAPHQL中上传文件...既简单又困难。

不用多久就会意识到_在GraphQL中上传文件是一大痛点_。文件上传一般都很复杂,即使在REST API中也是如此。经常有人断然建议在上传文件时考虑换回REST,但_真的有那么糟糕吗_我已经研究了一段时间了。_这里介绍一下如何用GraphQL上传文件_。

对于GraphQL文件上传来说,**最可行的选择似乎是Jayden Seric的多部分请求扩展,如果你喜欢维护一个单一的GraphQL端点,并通过GraphQL突变传入你的文件。或者你可以维护一个单独的端点来POST上传到(通常用REST HTTP方法实现)。第三种是在您的突变中使用第三方外部存储,如S3 URLS。

在GraphQL中上传文件并不是那么普遍。这些也许是因为没有官方支持,而且GraphQL文档对文件上传奇怪地保持沉默。

通常建议,除了你的GraphQL之外,简单地创建和端点(通常在REST中)来发布文件,通常就足够了。但如果你只想维护一个GraphQL端点呢?

让我们踢这是通过首先介绍REST是如何做文件上传,然后轻松进入使用这个后台上传文件到GraphQL服务器。

Uploading Files in REST

一个【REST胜过GraphQL的关键领域】(https://leapgraph.com/why-gra...。REST利用HTTP来处理图片等文件上传。

一个典型的REST图片上传看起来如下。

    `POST /images HTTP/1.1
    Authentication: Bearer < token >
    Host: localhost:4000
    Content-Type: image/jpeg
    Content-Length: 1254

    raw image content` 
  

基于URL的上传是以同样的方式使用application/json请求来处理的。

    `POST /images HTTP/1.1
    Host: localhost:4000
    Content-Type: image/jpeg
    Content-Length: 244

    {
      "image_url" : "https://cdn.example.org/image.png"
    }` 

在REST中上传文件通常需要三种不同的方法。

直接上传文件

这只是通过名称引用文件来上传。JSON数据通常与图片一起发送,但它可以被分割成一个不同的请求。

使用文件元数据上传

这种方法通常与多部分上传有关。文件被MultipartBoundry边界分隔符分割。多部分上传通常被认为是俗气的黑客,因为请求往往很快就会变得很大很乱(而且字段也会被分割)。

从外部URL上传

这是在上面第二个第二个请求中使用https://cdn.example.org/image.png做的。

一个多部分的上传会看起来像这样。

  `POST /images HTTP/1.1
    Host: localhost:4000
    Authentication: Bearer < token >
    Content-Type: multipart/form-data; boundary=MultipartBoundry
    Accept-Encoding: gzip, deflate

    --MultipartBoundry
    Content-Disposition: form-data; name="image"; filename="458485515151024_454541324960893_3451511151369966555525_n.jpg"
    Content-Type: image/jpeg

    raw image content
    --MultipartBoundry
    Content-Disposition: form-data; name="imageJsonData"
    Content-Type: application/json

    --MultipartBoundry--` 

How To Upload Files in GraphQL

在GraphQL中上传文件并非易事。首先GraphQL不像REST那样利用HTTP方法。然后是单一的端点。

让我们看看GraphQL中上传文件的一些方法。

Uploading with GraphQL Mutations

GraphQL不允许在突变中使用原始文件。它只处理序列化数据。

有一些变通的方法可以解决这个问题。其中最有用的是

Uploading via REST Endpoints in GraphQL Mutations

在graphql突变里面,可以使用单独的REST API在graphql中上传文件。

使用这种方法又增加了一层复杂性。文件必须先上传到REST,然后在GraphQL突变中传递结果的上传URL。这通常是一个缓慢的过程,而且现在有两个服务器需要管理。

REST API使用之前概述的方法来上传文件。

Uploading Files as Base64 Encoded Strings

Base64编码的字符串可以通过GraphQL突变。

编码后的字符串通常比其二进制对应物大,但有三分之一。

字符串的编码也可以很快地成为资源密集型的,而且它有时充满了错误。

Uploading file using External URLs (such as AWS S3)

另一种上传文件到GrapQL的方式是使用S3。一旦一个文件上传到S3并生成一个文件url id,该url就可以在Graph Mutation中使用,将文件存储在GraphQL服务器中。

Uploading Files using apollo-upload-server

apollo-upload-server是一个库,它允许你在graphql突变中上传文件,而不需要创建一个REST端点来处理这些上传。

它使用一个名为multipart request spec的扩展来处理文件传输。

然后,要上传的文件可以在GraphQL突变中的任何地方使用如下变量进行嵌套。

  {
  query: `
    mutation($image: Upload!) {
      uploadImage(image: $image) {
        id
      }
    }
  `,
  variables: {
    image: Image // image.jpg
  }
} 

该文件就像其他突变参数一样被添加。

Apollo Upload是用apollo-upload-servernpm包安装的,在Apollo Server和Express中实现如下。

  `import { apolloUploadExpress } from 'apollo-upload-server'

    ...

    app.use(
      '/graphql',
      bodyParser.json(),
      apolloUploadExpress(/* Options */),
      graphqlExpress(/* … */)` 

这些选项用于设置最大文件(maxFiles)、文件上传大小(maxFileSize)和字段大小(maxFieldSize)。

文件上传标量被添加到类型和解析器中,具体如下:

  ``import { makeExecutableSchema } from 'graphql-tools'
    import { apolloUploadExpress, GraphQLUpload } from 'apollo-upload-server'
    -*
    const schema = makeExecutableSchema({
      typeDefs: `scalar Upload`,
      resolvers: { Upload: GraphQLUpload }
    })`` 

用多部分请求滚动你自己的上传者。

另一种选择是在你的多部分请求上滚动。这将代替使用apollo-upload-server(和apollo-upload-client),尽管这两种方法有很多相似之处,例如它们利用了GraphQL-request。

Jayden Seric多部分扩展与滚动自己的方法相比也有一些优势,例如解析器中的文件上传流和中止文件上传的能力。

要滚动您自己的上传器,您将使用GraphQL-request发送任意数据的能力,而不是常规的POST-request--这就是您发送多部分请求的方式。

对于多部分请求,GraphQL需要一个query字段。

在我们的GraphQL服务器上,多部分请求被读入一个request对象,然后被传递到解析器上下文中。

客户端也需要一个代码NetworkInterface来处理多部分请求。


Reco
4.6k 声望541 粉丝

敢作敢为