Next.js Apollo Client向NestJS GraphQL传文件数组后端接收为空的问题
解决Next.js Apollo Client向NestJS GraphQL传File数组后端接收空对象的问题
核心问题原因
GraphQL默认用JSON格式传输数据,无法直接传递File对象。必须通过multipart/form-data协议处理文件上传,你的前后端都缺少对应配置和正确的类型处理逻辑。
后端NestJS修正步骤
1. 安装依赖并配置上传中间件
先安装graphql-upload依赖:
npm install graphql-upload
在AppModule的GraphQL配置中添加文件上传处理中间件:
import { GraphQLModule } from '@nestjs/graphql'; import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo'; import { graphqlUploadExpress } from 'graphql-upload'; @Module({ imports: [ GraphQLModule.forRoot<ApolloDriverConfig>({ driver: ApolloDriver, autoSchemaFile: true, context: ({ req }) => ({ req }), // 注册上传中间件,可根据需求调整文件大小和数量限制 onModuleInit: async (app) => { app.use(graphqlUploadExpress({ maxFileSize: 10 * 1024 * 1024, maxFiles: 10 })); }, }), ], }) export class AppModule {}
2. 修正CreateTaskDto类型定义
确保attachments字段使用GraphQLUpload数组类型:
import { InputType, Field } from '@nestjs/graphql'; import { GraphQLUpload, Upload } from 'graphql-upload'; @InputType() export class CreateTaskDto { @Field(() => String) name: string; @Field() priority: string; @Field(() => [String], { nullable: true }) label?: string[]; @Field({ nullable: true }) owner?: string; @Field({ nullable: true }) assignee?: string; @Field({ nullable: true }) dueDate?: string; // 正确声明为Upload数组类型 @Field(() => [GraphQLUpload], { nullable: true }) attachments?: Upload[]; @Field({ nullable: true }) description?: string; }
3. 正确解析Upload对象
Upload是Promise类型,必须通过await解析才能拿到文件实际信息:
async create(createTaskDto: CreateTaskDto): Promise<TaskResponseToUser> { // 解析所有上传的文件 const resolvedAttachments = createTaskDto.attachments ? await Promise.all( createTaskDto.attachments.map(async (upload) => { const { createReadStream, filename, mimetype, encoding } = await upload; // 这里可添加文件保存逻辑(写入本地/云存储等) return { filename, mimetype, encoding }; }) ) : []; console.log(resolvedAttachments); // 现在能看到正常的文件信息 return { message: 'Task created.', status: true, data: { ...createTaskDto, attachments: resolvedAttachments, }, }; }
前端Next.js Apollo Client修正步骤
1. 安装上传支持依赖
npm install apollo-upload-client
2. 替换Apollo Client的Link为上传专用Link
用createUploadLink替换默认的createHttpLink,它会自动将File对象转换为multipart/form-data请求:
import { ApolloClient, InMemoryCache } from '@apollo/client'; import { createUploadLink } from 'apollo-upload-client'; const client = new ApolloClient({ link: createUploadLink({ uri: '/api/graphql', // 你的GraphQL接口地址 }), cache: new InMemoryCache(), });
3. 保持现有调用逻辑
你的saveTask函数无需修改,filesSelected作为File数组直接传递即可:
function saveTask() { const createTaskDto = { name: title, priority, label: labels, owner, assignee, dueDate, attachments: filesSelected, description }; if (title) { createTask({ variables: { createTaskDto } }) .then(res => console.log(res)) .catch(err => console.log(err)); } }
关键注意事项
- 不要用自定义
AnyType处理文件上传,GraphQLUpload是官方标准类型 - 后端必须配置
graphqlUploadExpress中间件,否则无法解析multipart请求 - 前端必须使用
createUploadLink,否则Apollo Client会把File序列化为JSON,导致后端收到空对象 Upload是Promise类型,必须await解析才能获取实际文件数据
内容的提问来源于stack exchange,提问作者Gagan
相关产品推荐
相关产品推荐

