首页
/ GraphQL Yoga 文件上传功能详解

GraphQL Yoga 文件上传功能详解

2025-07-07 01:57:20作者:彭桢灵Jeremy

概述

GraphQL Yoga 作为一款功能强大的 GraphQL 服务器实现,提供了对 GraphQL 多部分请求规范(GraphQL Multipart Request Specification)的完整支持。这意味着开发者可以轻松实现文件上传功能,并通过 HTTP 在 GraphQL 解析器中处理二进制数据。

核心特性

GraphQL Yoga 处理上传文件时,会将其转换为符合 WHATWG 标准的 FileBlob 对象。这些对象与浏览器 API 中的文件对象完全一致,使得前端开发者能够无缝过渡到服务端处理。

快速入门

1. 添加 File 标量类型

首先,你需要在 GraphQL 模式中定义一个 File 标量类型:

scalar File

type Mutation {
  readTextFile(file: File!): String!
  saveFile(file: File!): Boolean!
}

2. 实现解析器

在解析器中,你可以直接使用 File 对象提供的方法处理上传的文件:

Mutation: {
  readTextFile: async (_, { file }: { file: File }) => {
    const textContent = await file.text()
    return textContent
  },
  saveFile: async (_, { file }: { file: File }) => {
    try {
      const fileArrayBuffer = await file.arrayBuffer()
      await fs.promises.writeFile(
        path.join(__dirname, file.name),
        Buffer.from(fileArrayBuffer)
      )
      return true
    } catch (e) {
      return false
    }
  }
}

3. 测试上传功能

可以使用 curl 命令测试文件上传功能:

curl localhost:4000/graphql \
  -F operations='{ "query": "mutation ($file: File!) { readTextFile(file: $file) }", "variables": { "file": null } }' \
  -F map='{ "0": ["variables.file"] }' \
  -F 0=@mytext.txt

高级配置

禁用文件上传

如果需要禁用多部分请求处理,可以在创建 Yoga 实例时设置:

createYoga({ multipart: false })

配置上传限制(仅限 Node.js 环境)

在 Node.js 环境中,可以配置多部分请求处理的各项限制:

import { createFetch } from '@whatwg-node/fetch'

createYoga({
  fetchAPI: createFetch({
    formDataLimits: {
      fileSize: 1000000,  // 最大文件大小(字节)
      files: 10,         // 最大文件数量
      fieldSize: 1000000, // 最大内容大小
      headerSize: 1000000 // 最大头部大小
    }
  })
})

第三方集成方案

与 GraphQL Nexus 集成

GraphQL Nexus 是一个流行的 TypeScript GraphQL 模式构建库。集成示例如下:

const FileScalar = scalarType({
  name: 'File',
  asNexusMethod: 'file',
  description: '文件上传标量类型',
  sourceType: 'File'
})

const readTextFile = mutationField('readTextFile', {
  type: 'String',
  args: { file: nonNull(arg({ type: 'File' })) },
  resolve: async (_, { file }) => {
    return await file.text()
  }
})

与 S3 存储集成

可以将上传的文件直接存储到 S3 或其他兼容存储服务:

const client = new S3Client({})

Mutation: {
  upload: async (_, { file }: { file: File }) => {
    await client.send(
      new PutObjectCommand({
        Bucket: 'test-bucket',
        Key: file.name,
        Body: Buffer.from(await file.arrayBuffer())
      })
    )
    return true
  }
}

最佳实践

  1. 文件大小验证:始终在业务逻辑中验证文件大小,即使配置了服务器限制
  2. 文件类型检查:通过文件扩展名或 MIME 类型验证文件格式
  3. 错误处理:为文件操作提供详细的错误反馈
  4. 流式处理:对于大文件,考虑使用流式处理而非完全加载到内存

通过 GraphQL Yoga 的文件上传功能,开发者可以轻松构建支持文件上传的 GraphQL API,同时保持代码的简洁性和可维护性。