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

Node.js Express中Axios通用工具适配PDF响应的问题咨询

解决方案

关于默认响应类型下转PDF的问题

不行,默认响应类型(json或text)返回的字符串无法还原成有效的PDF文件。因为axios会把二进制响应(比如PDF)按文本编码(默认UTF-8)解析成字符串,这个过程中二进制数据会被不可逆地损坏——多字节的二进制值会被错误转码,丢失原始字节信息,所以再转回去也无法得到正确的PDF文件。必须用二进制类型的responseType(arraybuffer或blob)来获取原始二进制数据。

动态适配响应类型的可行方案

axios无法在收到响应后再设置responseType,因为这个参数是请求前就确定的,决定了axios如何解析响应数据。不过可以通过以下两种方式实现动态适配:

方案1:让调用者指定响应类型(推荐)

给工具函数添加可选的responseType参数,默认值设为json,需要获取文件时传入arraybuffer或blob。同时在错误处理中,针对二进制响应类型做兼容——如果错误响应的Content-Type是JSON格式,就把二进制buffer转成字符串再解析成JSON对象。

修改后的代码示例:

function axiosCall(method, endpoint, body, responseType = 'json') {
    let requestConfig = {
        url: encodeURI(`${endpoint.host}:${endpoint.port}${endpoint.path}`),
        method: method,
        proxy: false,
        data: body,
        responseType: responseType, // 新增响应类型参数
        headers: {
            "x-access-token": token,
            "X-Correlation-ID": correlationId,
            "Content-Type": "application/json"
        },
    };

    return axios.request(requestConfig).then(response => {
        return response.data;
    }).catch((errorRes) => {
        let errorDetails = {
            error: errorRes.message,
            status: errorRes?.response?.status || 500,
            responseContent: "Server Error"
        };

        // 处理二进制响应类型下的JSON错误
        if (errorRes?.response?.data && responseType === 'arraybuffer') {
            const contentType = errorRes.response.headers['content-type'];
            if (contentType?.includes('application/json')) {
                // 把buffer转成UTF-8字符串再解析成JSON
                errorDetails.responseContent = JSON.parse(Buffer.from(errorRes.response.data).toString('utf8'));
            } else {
                // 非JSON的二进制错误,直接返回buffer
                errorDetails.responseContent = errorRes.response.data;
            }
        } else {
            errorDetails.responseContent = errorRes?.response?.data || "Server Error";
        }

        throw errorDetails;
    });
}

调用示例:

  • 获取JSON:axiosCall('GET', endpoint, null)
  • 获取PDF:axiosCall('GET', pdfEndpoint, null, 'arraybuffer')

方案2:先通过HEAD请求获取Content-Type再发起请求

先发送一个HEAD请求到目标接口,拿到响应头的Content-Type,判断是否是二进制类型(比如application/pdf、image/png等),再决定设置哪种responseType发起实际请求。但这个方案有两个缺点:

  • 多一次HTTP请求,增加开销和延迟
  • 部分接口的HEAD响应和实际请求(比如POST)的Content-Type可能不一致,存在适配风险

示例代码(仅作参考):

async function axiosCall(method, endpoint, body) {
    // 先发送HEAD请求获取Content-Type
    const headResponse = await axios.head(encodeURI(`${endpoint.host}:${endpoint.port}${endpoint.path}`), {
        headers: {
            "x-access-token": token,
            "X-Correlation-ID": correlationId
        }
    });

    const contentType = headResponse.headers['content-type'];
    let responseType = 'json';
    // 判断是否为二进制类型
    const binaryTypes = ['application/pdf', 'image/png', 'image/jpeg', 'application/octet-stream'];
    if (binaryTypes.some(type => contentType?.includes(type))) {
        responseType = 'arraybuffer';
    }

    // 发起实际请求
    let requestConfig = {
        url: encodeURI(`${endpoint.host}:${endpoint.port}${endpoint.path}`),
        method: method,
        proxy: false,
        data: body,
        responseType: responseType,
        headers: {
            "x-access-token": token,
            "X-Correlation-ID": correlationId,
            "Content-Type": "application/json"
        },
    };

    return axios.request(requestConfig).then(response => {
        return response.data;
    }).catch((errorRes) => {
        // 错误处理逻辑同方案1
        let errorDetails = {
            error: errorRes.message,
            status: errorRes?.response?.status || 500,
            responseContent: "Server Error"
        };

        if (errorRes?.response?.data && responseType === 'arraybuffer') {
            const errContentType = errorRes.response.headers['content-type'];
            if (errContentType?.includes('application/json')) {
                errorDetails.responseContent = JSON.parse(Buffer.from(errorRes.response.data).toString('utf8'));
            } else {
                errorDetails.responseContent = errorRes.response.data;
            }
        } else {
            errorDetails.responseContent = errorRes?.response?.data || "Server Error";
        }

        throw errorDetails;
    });
}

总结

优先选择方案1,让调用者按需指定responseType,既灵活又避免额外请求开销。二进制响应的错误处理只需针对JSON格式做转码即可,其他二进制错误直接返回原始buffer即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 08:15:43