You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apollo Express GraphQL文件上传Mutation前端调用返回404问题咨询

问题原因
  • 核心错误是前端代码中Dropzone返回的acceptedFiles是文件数组,你直接将整个数组传给了定义为单个Upload!类型的file变量,参数类型不匹配导致请求格式异常,触发404错误。
  • 次要潜在问题:如果你的Apollo客户端同时配置了默认的HttpLink,会和createUploadLink产生冲突,覆盖上传专用的请求逻辑。
  • 额外隐性问题:你的服务端流写入的await finished写法不符合异步规范,回调式写法无法被await捕获,会导致流还没写入完成就提前返回结果,也可能引发请求异常。
解决方法

1. 修复前端传参错误

修改Dropzone的onDrop回调,取数组第一个元素传给file变量,适配单文件上传的定义:

<Dropzone onDrop={acceptedFiles => {
  if(acceptedFiles?.length) {
    uploadImage({variables: {file: acceptedFiles[0]}})
  }
}}>
{({getRootProps, getInputProps}) => (
    <section>
        <div {...getRootProps()}>
            <input {...getInputProps()} />
            <p>拖拽文件到此处,或点击选择文件上传</p>
        </div>
    </section>
)}
</Dropzone>

2. 确认Apollo客户端配置正确

确保没有额外配置HttpLink,createUploadLink是唯一的链路配置,避免链路冲突:

import { ApolloClient, InMemoryCache, createUploadLink } from '@apollo/client';

const client = new ApolloClient({
    link: createUploadLink({
        uri: 'http://localhost:4000/graphql'
    }),
    cache: new InMemoryCache(),
});

3. 修复服务端流写入逻辑

将回调式的流写入改为Promise封装,确保await能正确等待流写入完成:

import {GraphQLUpload} from "graphql-upload"
// ...
Upload: GraphQLUpload,
Mutation: {
   singleUpload: async (parent, {file, vacId, index}) => {
   const {createReadStream, filename, mimetype, encoding} = await file;
   const stream = createReadStream();
   const nameToBe = `${vacId}-${index}.${filename.split('.').pop()}`;
   const location = path.join(__dirname, `../images/${nameToBe}`)
   const out = createWriteStream(location);

   // 改写为Promise封装的流写入逻辑
   await new Promise((resolve, reject) => {
     stream.pipe(out)
     out.on('finish', resolve)
     out.on('error', (err) => {
       console.error("流写入失败", err)
       reject(err)
     })
   })

   return {filename, mimetype, encoding, url: `http://localhost:4000/static/${nameToBe}`};
   }
}

4. 确认服务端中间件顺序

你当前的中间件加载顺序是正确的,graphqlUploadExpress必须在server.applyMiddleware之前加载,不需要调整:

app.use(graphqlUploadExpress());
app.use('/static', express.static("./images"));
server.applyMiddleware({app})

内容的提问来源于stack exchange,提问作者Nils

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 22:15:02