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

Apollo Server 4 社交媒体后端图片上传GraphQL API开发方案求助

在Apollo Server 4中实现图片上传的GraphQL API(ES6方案)

Apollo Server 4不再内置文件上传支持,graphql-upload也因架构变更无法直接兼容,下面是基于Express和Formidable的ES6解决方案:

1. 安装依赖

npm install @apollo/server apollo-server-express express formidable graphql

2. 配置服务器与文件解析中间件

创建server.js文件,搭建Express服务并添加Formidable中间件处理multipart/form-data请求:

import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import express from 'express';
import { createReadStream } from 'fs';
import { mkdir, writeFile } from 'fs/promises';
import { IncomingForm } from 'formidable';
import path from 'path';
import { fileURLToPath } from 'url';

// 处理ES6模块的目录路径
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const app = express();

// 解析multipart请求的中间件
app.use(async (req, res, next) => {
  if (req.method !== 'POST' || !req.is('multipart/form-data')) {
    return next();
  }

  const form = new IncomingForm({
    uploadDir: path.join(__dirname, 'uploads'),
    keepExtensions: true,
    maxFileSize: 5 * 1024 * 1024, // 限制单文件5MB
  });

  // 确保uploads目录存在
  await mkdir(form.uploadDir, { recursive: true });

  form.parse(req, (err, fields, files) => {
    if (err) return next(err);
    req.body = fields;
    req.files = files;
    next();
  });
});

3. 定义GraphQL Schema

添加支持文件上传的Mutation类型:

const typeDefs = `
  type Post {
    id: ID!
    content: String!
    imageUrl: String
  }

  type Mutation {
    createPost(content: String!, image: Upload): Post
  }
`;

4. 实现Resolver处理文件上传

在Resolver中获取解析后的文件,完成存储并生成访问URL:

let postIdCounter = 1;

const resolvers = {
  Mutation: {
    createPost: async (_, { content }, { req }) => {
      let imageUrl = null;

      if (req.files?.image) {
        const image = req.files.image;
        // 重命名文件避免冲突
        const newFilename = `${Date.now()}-${image.originalFilename}`;
        const newFilePath = path.join(__dirname, 'uploads', newFilename);
        
        // 保存文件到指定目录
        await writeFile(newFilePath, createReadStream(image.filepath));
        // 生成静态访问URL(需配置静态托管)
        imageUrl = `/uploads/${newFilename}`;
      }

      // 示例:内存存储帖子,实际项目替换为数据库操作
      const post = {
        id: postIdCounter++,
        content,
        imageUrl,
      };

      return post;
    },
  },
};

5. 启动服务并配置静态托管

将Apollo Server集成到Express,并托管uploads目录让前端可访问图片:

async function startServer() {
  const server = new ApolloServer({ typeDefs, resolvers });
  await server.start();

  app.use(
    '/graphql',
    express.json(),
    expressMiddleware(server, {
      context: async ({ req }) => ({ req }),
    })
  );

  // 静态托管uploads目录
  app.use('/uploads', express.static(path.join(__dirname, 'uploads')));

  app.listen({ port: 4000 }, () => {
    console.log('🚀 Server running at http://localhost:4000/graphql');
  });
}

startServer().catch(err => console.error(err));

测试上传

在Apollo Sandbox中执行以下Mutation,选择本地图片作为image参数:

mutation CreatePost($content: String!, $image: Upload) {
  createPost(content: $content, image: $image) {
    id
    content
    imageUrl
  }
}

注意事项

  • 可根据需求调整文件大小限制、存储路径,或替换为云存储(如AWS S3)。
  • 生产环境需添加文件类型校验(只允许图片格式)、错误捕获逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 01:07:34