如何从Node.js服务器向Rails GraphQL后端实现服务器到服务器的本地文件上传?
我刚好处理过类似的Node.js服务器端向Rails GraphQL后端上传文件的场景,给你梳理下正确的解决思路和代码实现:
解决Node.js服务器端Apollo文件上传的问题
你遇到的核心问题是:浏览器环境的File对象和Node.js环境的文件操作结构完全不同,apollo-upload-client在Node环境下需要特定格式的对象才能识别为可上传文件,直接传fs.ReadStream或Node版Blob都不符合要求。
正确的方案:构造符合Apollo上传要求的对象
apollo-upload-client在Node环境中会识别包含以下三个属性的对象作为上传文件:
createReadStream: 返回文件读取流的函数filename: 后端将接收的文件名mimetype: 文件的MIME类型(比如image/jpeg、text/plain)
下面是完整的可运行代码:
首先导入所需模块:
import fs from "fs" import { ApolloClient, InMemoryCache } from "@apollo/client" import { createUploadLink } from "apollo-upload-client" import type { NextApiRequest, NextApiResponse } from "next" import * as Generated from "src/generated/graphql"
创建一个工具函数来生成符合要求的上传对象:
// 工具函数:生成Apollo上传所需的文件对象 const generateUploadFile = (filePath: string, filename: string, mimetype: string) => { return { filename, mimetype, createReadStream: () => fs.createReadStream(filePath), } }
然后在你的API路由中使用这个函数:
const client = new ApolloClient({ cache: new InMemoryCache(), link: createUploadLink({ uri: "http://backend:3000/graphql", }), }) // 验证连接的代码可以保留 client .query<Generated.TestFieldQuery, Generated.TestFieldQueryVariables>({ query: Generated.TestFieldDocument, variables: {}, }) .then(({ data }) => { console.log("连接正常,返回数据:", data) }) export default async (req: NextApiRequest, res: NextApiResponse) => { try { // 构造上传文件对象 const file = generateUploadFile("./test.jpg", "test.jpg", "image/jpeg") const { data } = await client.mutate< Generated.TestMutationMutation, Generated.TestMutationMutationVariables >({ mutation: Generated.TestMutationDocument, variables: { input: { file, }, }, fetchPolicy: "no-cache", }) console.log("文件上传成功:", data) res.status(200).json({ success: true, data }) } catch (error) { console.error("文件上传失败:", error) res.status(500).json({ success: false, error: error instanceof Error ? error.message : "未知错误" }) } }
为什么之前的尝试失败?
- 直接传
fs.createReadStream:这个返回的ReadStream对象缺少filename和mimetype属性,后端无法将其识别为一个合法的上传文件。 - 使用Node版
Blob:Node.js从buffer模块导入的Blob和浏览器原生Blob结构差异很大,apollo-upload-client在Node环境下不把它当作上传文件处理,因此会报错{} is not a valid upload。
后端兼容性说明
你的Rails后端已经配置了apollo_upload_server,它会自动将这种格式的上传解析为ActionDispatch::Http::UploadedFile对象,和客户端上传的格式完全一致,所以不需要修改任何后端代码。
另外要注意,必须使用createUploadLink作为Apollo客户端的链接,不能用普通的HttpLink,否则文件上传的多部分表单请求无法被正确处理。
内容的提问来源于stack exchange,提问作者kukrt
相关产品推荐
相关产品推荐

