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

如何将响应文件数据转为可下载文件?Blob生成文件不可读排查

如何将API响应转换为可下载文件URL?生成的文件无法读取问题排查

我尝试用Blob方法把API响应转成可下载文件URL,但生成的文件无法读取,问题出在哪?

我的尝试

let blob = new Blob([data.data], {type: "octet/stream"});
var url  = window.URL.createObjectURL(blob);
window.location.assign(url);

获取文件数据的API请求

export const getDocumentByFileName = async (fileName: string) => {
    const client = await Client();
    const response = await client.get(`${endpoint}/Documents/Get?fileName=${fileName}`, {
        responseType: 'blob',
    });
    if (!response.ok) {
        console.error('GET Document by fileName - ' + response.problem, response.data);
        return response;
    }

    // 204 No Content
    return response;
};

包含文件的响应数据

let data = {
    "duration": 92,
    "problem": null,
    "originalError": null,
    "ok": true,
    "status": 200,
    "headers": {
        "date": "Thu, 04 Aug 2022 10:36:28 GMT",
        "server": "Kestrel"
    },
    "config": {
        "url": "Documents/Get?fileName=afbaa8fb-2669-4cf1-ad69-726a408934f6..docx",
        "method": "get",
        "headers": {
            "Accept": "application/json",
            "locale": "en-gb"
        },
        "params": {
            "responseType": "arraybuffer"
        },
        "baseURL": "/",
        "transformRequest": [
            null
        ],
        "transformResponse": [
            null
        ],
        "timeout": 0,
        "xsrfCookieName": "XSRF-TOKEN",
        "xsrfHeaderName": "X-XSRF-TOKEN",
        "maxContentLength": -1,
        "maxBodyLength": -1,
        "transitional": {
            "silentJSONParsing": true,
            "forcedJSONParsing": true,
            "clarifyTimeoutError": false
        }
    },
    "data": "PK\u0003\u0004\u0014\u0000\u0006\u0000\b\u0000\u0000\u0000!\u0000ߤ�lZ\u0001\u0000\u0000 \u0005\u0000\u0000\u0013\u0000\b\u0002[Content_Types].xml �\u0004\u0002(�\u0000\u0002\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"
}

问题根源

  1. 响应格式配置冲突:你的API请求中,虽然设置了responseType: 'blob',但响应的config.params里包含了responseType: 'arraybuffer'——这会把responseType当成URL参数传给后端,而非Axios的响应解析配置。Axios默认会把二进制数据解析为UTF-8字符串,导致文件字节被篡改,生成的文件自然无法读取。
  2. 下载方式不严谨:直接使用window.location.assign(url)触发下载,部分浏览器可能无法正确识别文件类型或文件名,增加读取失败概率。

解决方案

步骤1:修正API请求配置

移除params中的responseType,确保Axios的responseType配置正确生效:

export const getDocumentByFileName = async (fileName: string) => {
    const client = await Client();
    const response = await client.get(`${endpoint}/Documents/Get?fileName=${fileName}`, {
        responseType: 'arraybuffer', // 推荐用arraybuffer,后续转换更灵活
        headers: {
            'Accept': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' // 明确指定文件类型
        }
    });
    if (!response.ok) {
        console.error('GET Document by fileName - ' + response.problem, response.data);
        return response;
    }
    return response;
};

步骤2:正确转换并触发下载

如果已经拿到被解析为字符串的二进制数据,先将其转回ArrayBuffer,再创建Blob并通过a标签触发下载:

// 将Unicode字符串转回ArrayBuffer
function stringToBuffer(str) {
    const buffer = new Uint8Array(str.length);
    for (let i = 0; i < str.length; i++) {
        buffer[i] = str.charCodeAt(i);
    }
    return buffer.buffer;
}

// 处理下载
const arrayBuffer = stringToBuffer(data.data);
const blob = new Blob([arrayBuffer], { 
    type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' 
});
const url = window.URL.createObjectURL(blob);

// 创建a标签触发下载
const downloadLink = document.createElement('a');
downloadLink.href = url;
downloadLink.download = '目标文件名.docx'; // 替换为实际文件名
document.body.appendChild(downloadLink);
downloadLink.click();

// 清理资源
document.body.removeChild(downloadLink);
window.URL.revokeObjectURL(url);

如果API请求修正后直接拿到ArrayBuffer或Blob,可以简化代码:

// 若response.data是ArrayBuffer
const blob = new Blob([response.data], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
// 后续下载逻辑同上

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 06:48:09