Socket.io传输FormData时服务端接收为空对象问题求解
问题根因
- Socket.IO 默认仅支持序列化普通 JSON 数据,
FormData是浏览器特有宿主对象,无标准 JSON 序列化规则,直接通过socket.emit传输时会被序列化为空对象,导致服务端收到空值。 - 即使服务端拿到了
FormData,现有 axios 调用方式也不符合 Discord Webhook 的文件上传规则,无法成功推送文件。
修复步骤
1. 客户端代码修改
不要直接传输 FormData,将文件转为 Base64 格式和普通字段一起传输,适配 Socket.IO 的序列化规则:
let url = window.location.href; let arr = url.split("/"); let result = arr[0] + "//" + arr[2]; const socket = io(result); // 不要在函数内重复初始化Socket连接,避免反复创建连接 async function sendMessage() { const file = document.getElementById("file").files[0]; // 将文件转为Base64格式 const fileReader = new FileReader(); fileReader.readAsDataURL(file); fileReader.onload = async () => { // 去掉Base64前缀,只保留编码内容 const base64File = fileReader.result.split(',')[1]; socket.emit('send-webhook', { fileName: file.name, fileType: file.type, fileBase64: base64File, content: "File Submited" }); } }
2. 服务端代码修改
首先安装依赖:npm install form-data
修改服务端逻辑,将收到的Base64转回二进制Buffer,构造符合要求的FormData发送给Discord Webhook:
const axios = require('axios'); const FormData = require('form-data'); io.on('connection', async socket => { socket.on('send-webhook', async data => { console.log(data); // 此时可正常收到所有字段 const formData = new FormData(); // 把Base64转回文件二进制流 const fileBuffer = Buffer.from(data.fileBase64, 'base64'); formData.append('content', data.content); formData.append('file', fileBuffer, { filename: data.fileName, contentType: data.fileType }); await axios .post('WEBHOOK_LINK', formData, { // 必须传入form-data专属请求头,Discord才能正确识别上传的文件 headers: formData.getHeaders() }) .catch(error => { console.error(error) }) }) });
可选优化
如果文件体积较大,Base64编码会增加约33%的传输体积开销,可改用HTTP POST接口直接上传FormData,不走Socket.IO传输文件,性能表现更好。
内容的提问来源于stack exchange,提问作者Drakeee0909
相关产品推荐
相关产品推荐

