Skip to content
GQLoom

文件上传

GQLoom 可通过 GraphQL 的 Upload 标量支持文件上传。
下面给出两种常见接入方式:

  • 使用 graphql-uploadgraphql-upload-minimalGraphQLUpload 标量
  • 使用 graphql-yoga 提供的 File 类型

核心步骤

  • 使用 silk 函数申明 UploadFile 标量。
  • mutationinput 中使用 UploadFile 标量。

使用 GraphQLUpload

以下代码示例适用于 graphql-uploadgraphql-upload-minimal

ts
import { 
mutation
,
resolver
,
silk
,
weave
} from "@gqloom/core"
import {
ValibotWeaver
} from "@gqloom/valibot"
import {
GraphQLNonNull
} from "graphql"
import { type FileUpload,
GraphQLUpload
} from "graphql-upload-minimal"
import {
createServer
} from "node:http"
import {
createWriteStream
} from "node:fs"
import {
pipeline
} from "node:stream/promises"
import * as
path
from "node:path"
import * as
fsPromises
from "node:fs/promises"
import {
createYoga
} from "graphql-yoga"
import * as
v
from "valibot"
const
Upload
=
silk
<
Promise
<FileUpload>>(new
GraphQLNonNull
(
GraphQLUpload
))
const
uploadResolver
=
resolver
({
upload
:
mutation
(
v
.
string
())
.
input
({
fileName
:
v
.
nullish
(
v
.
string
()),
file
:
Upload
,
}) .
resolve
(async ({
fileName
,
file
}) => {
const {
filename
,
createReadStream
} = await
file
const
name
=
fileName
??
filename
const
uploadsDir
=
path
.
join
(import.meta.
dirname
, "uploads")
await
fsPromises
.
mkdir
(
uploadsDir
, {
recursive
: true })
const
rs
=
createReadStream
()
const
ws
=
createWriteStream
(
path
.
join
(
uploadsDir
,
name
))
await
pipeline
(
rs
,
ws
)
return `file uploaded: ${
name
}`
}), })

要点:

使用 File 类型

以下代码示例适用于 graphql-yogaFile 类型。

ts
import { 
mutation
,
resolver
,
silk
,
weave
} from "@gqloom/core"
import {
ValibotWeaver
} from "@gqloom/valibot"
import {
GraphQLNonNull
,
GraphQLScalarType
} from "graphql"
import {
createServer
} from "node:http"
import * as
path
from "node:path"
import * as
fs
from "node:fs/promises"
import {
createYoga
} from "graphql-yoga"
import * as
v
from "valibot"
const
FileScalar
=
silk
(
new
GraphQLNonNull
(
new
GraphQLScalarType
<File, File>({
name
: "File",
description
: "The `File` scalar type represents a file upload.",
}) ) ) const
uploadResolver
=
resolver
({
upload
:
mutation
(
v
.
string
())
.
input
({
fileName
:
v
.
nullish
(
v
.
string
()),
file
:
FileScalar
,
}) .
resolve
(async ({
fileName
,
file
}) => {
const
name
=
fileName
??
file
.
name
const
uploadsDir
=
path
.
join
(import.meta.
dirname
, "uploads")
await
fs
.
mkdir
(
uploadsDir
, {
recursive
: true })
await
fs
.
writeFile
(
path
.
join
(
uploadsDir
,
name
),
Buffer
.
from
(await
file
.
arrayBuffer
())
) return `file uploaded: ${
name
}`
}), }) const
schema
=
weave
(
ValibotWeaver
,
uploadResolver
)
const
yoga
=
createYoga
({
schema
})
createServer
(
yoga
).
listen
(4000)

要点:

  • Yoga 提供的 File 直接支持 arrayBuffer(),适合中小文件或先落盘再处理。
  • 同样通过 silk 包装为非空标量,按需补充校验与权限控制。