如何修改apollo-upload-client文件上传payload的name属性?
解决方案:修改apollo-upload-client的form-data name属性
好的,我来帮你搞定这个问题!默认情况下,apollo-upload-client确实会用数字索引(比如"0")作为form-data的name属性,不过我们可以通过自定义序列化逻辑来改成你想要的自定义变量名。
核心思路
apollo-upload-client的工作流程是:
- 遍历GraphQL变量,把File对象替换成指向变量路径的引用(比如
["variables.someCustomName"]) - 生成一个映射表,用数字键关联引用和对应的文件
- 把文件以数字键作为name存入form-data
我们要做的就是修改这个映射表的键生成逻辑,把数字换成你的变量名(比如someCustomName)。
具体实现步骤
自定义序列化函数
参考官方默认的serializeUploads函数,我们改写它的键生成规则,用变量的名称作为映射键,而不是递增数字:import { createUploadLink } from 'apollo-upload-client'; // 自定义序列化函数,将映射键改为变量名 const customSerializeUploads = (variables) => { const uploadMap = new Map(); const files = []; // 递归遍历变量,定位所有File对象并记录变量路径 const traverse = (obj, path = []) => { if (obj instanceof File) { // 用变量名(路径的最后一段)作为映射键 const variableName = path[path.length - 1]; // 记录映射关系:变量名 -> 变量路径 uploadMap.set(variableName, [`variables.${path.join('.')}`]); files.push({ key: variableName, file: obj }); return null; // 将变量中的File替换为null,后续由映射表处理 } if (typeof obj === 'object' && obj !== null) { for (const key in obj) { if (obj.hasOwnProperty(key)) { obj[key] = traverse(obj[key], [...path, key]); } } } return obj; }; const serializedVariables = traverse(JSON.parse(JSON.stringify(variables))); return { operation: serializedVariables, map: Object.fromEntries(uploadMap), files: files.map(item => ({ name: item.key, file: item.file })) }; };使用自定义序列化函数创建上传链接
在初始化Apollo Client的上传链接时,传入我们的自定义函数:const uploadLink = createUploadLink({ uri: '/your-graphql-api-endpoint', // 替换成你的GraphQL地址 serializeUploads: customSerializeUploads // 传入自定义序列化逻辑 }); // 把uploadLink加入Apollo Client的链接链中 const client = new ApolloClient({ link: uploadLink, cache: new InMemoryCache() });服务器端适配
注意:你的GraphQL服务器端也需要对应调整解析逻辑,因为默认的apollo-upload-server是基于数字键来解析文件的。如果用的是apollo-upload-server,你需要修改它的解析代码,支持从自定义变量名的form-data字段中读取文件。
效果验证
当你使用变量名someCustomName上传文件时,生成的payload会变成你想要的样子:
... { "someCustomName": ["variables.someCustomName"] } --------------------------cec8e8123c05ba25 Content-Disposition: form-data; name="someCustomName"; filename="a.txt" Content-Type: text/plain
内容的提问来源于stack exchange,提问作者Eva
相关产品推荐
相关产品推荐

