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

如何通过HTTP POST请求发送Blob数据并附带JWT认证字符串参数?

问题分析与解决方案

你的代码目前无法正确发送Blob数据和认证参数,核心问题在于没有用正确的方式封装混合类型的请求体,同时请求头的处理逻辑不符合多类型数据传输的要求。以下是修正后的实现方案:

1. 用FormData封装请求参数

要同时发送字符串参数和Blob数据,必须使用FormData来封装,它会自动处理多类型数据的编码:

// 创建FormData实例并添加参数
const formData = new FormData();
formData.append('uname', user.uname);
formData.append('authKey', user.authKey); // 若authKey是JWT,更建议放在请求头中(见下方说明)
formData.append('video', qde.debrief.blob, 'video-file.mp4'); // 第三个参数可指定文件名称,便于后端识别

// 调用修正后的xhrRequest
const xhr = await xhrRequest(`${serverIp}/api/file`, "POST", formData, 'multipart');
prom.push(xhr);

2. 修正xhrRequest函数

原函数存在请求体序列化错误、响应解析容错性差等问题,以下是优化后的版本:

function xhrRequest(url, type, body, header) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                let responseBody;
                // 兼容非JSON格式的响应,避免解析报错
                try {
                    responseBody = JSON.parse(xhr.response);
                } catch (e) {
                    responseBody = xhr.response || "未知错误";
                }
                // 统一处理成功/失败状态
                resolve({ 
                    error: xhr.status !== 200, 
                    body: responseBody 
                });
            }
        }
        xhr.timeout = 5000;
        xhr.ontimeout = () => {
            resolve({ error: true, body: "连接服务器超时" });
        }
        xhr.onerror = function () {
            resolve({ error: true, body: "服务器连接失败" });
        }
        xhr.open(type, url, true);

        // --- 可选:JWT认证放在请求头(更规范安全)---
        // 如果authKey是JWT令牌,建议改用请求头传递,注释掉上方FormData中的authKey后启用以下代码
        // if (typeof body === 'object' && !(body instanceof FormData) && body.authKey) {
        //   xhr.setRequestHeader('Authorization', `Bearer ${body.authKey}`);
        //   delete body.authKey; // 从请求体中移除
        // }

        if (type === "POST") {
            // 仅在发送普通urlencoded参数时手动设置请求头
            if (header === 'application/x-www-form-urlencoded' && !(body instanceof FormData)) {
                xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
                // 将普通对象序列化为urlencoded格式
                body = new URLSearchParams(body).toString();
            }
            // 发送FormData时,浏览器会自动设置正确的multipart/form-data头(包含boundary),无需手动设置
            xhr.send(body);
        } else {
            xhr.send();
        }
    })
}

关键说明

  • FormData的必要性:直接发送包含Blob的普通对象会被浏览器转成[object Object],完全无法解析;FormData会自动处理Blob的编码和边界分隔符,确保后端能正确解析文件。
  • JWT认证的最佳实践:将JWT令牌放在Authorization: Bearer <token>请求头中,比作为表单参数更安全,也符合RESTful规范。如果采用这种方式,只需在xhrRequest中添加设置请求头的逻辑,无需将authKey放入FormData。
  • 请求头的自动处理:发送FormData时,不要手动设置Content-Type: multipart/form-data,浏览器自动生成的头会包含必要的boundary参数,手动设置会导致后端解析失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 02:10:18