因公司架构缘由前端请求须要通过NodeJs进行接口转发再返回到浏览器,在对导出Excel接口进行代理请求时发现导出到浏览器的数据出现乱码的状况,一顿操做最后发现是编码的问题。javascript
即使java后端已经对数据作了处理,经node接口请求响应以后文件流的编码仍是被修改了,以前一直想着应该以一对一的请求响应处理方式去获取最原始的数据的心理设定做祟,不该对响应response作处理,而是应该直接拿到什么返回什么。一直没往编码问题方向去思考,一番折腾甚至使用了三种不一样的请求方式仍是返回乱码数据,不由开始怀疑本身这几年前端是否是白作了,还适合作开发吗??是否是该转行去送外卖了...前端
排错思路:java
使用postman直接请求后端接口,不通过nodeJs转发。复制postman请求后生成的curl命令代码,打开命令行工具进行粘贴,并在最末尾添加-o test_java.xls
后回车,将请求获得的文件流保存为Excel后打开查看的方式看看是否是java后端的接口自己就有问题,我这里打开后发现数据工工整整排列整齐...node
打开浏览器控制台并切换到network模块下,右键移动到Copy选项,点击Copy as cURL
,仿造上一步在命令最末尾追加-o test_nodeJs.xls
打开文件查看是否出现乱码,我在这一步发现打开后的文件全是乱码...问题就出在NodeJs对后端接口的请求上ios
假设上面两步打开以后发现文件均没有问题,那么就是前端客户端对文件流的处理代码逻辑上有问题json
如下是个人客户端代码,没有问题...axios
建立a标签并模拟点击事件下载Excel文件后端
if (isBlob(res.data)) {
const filename = decodeURIComponent(
headers['content-disposition'].match(/(filename=(.*))/)[2]
); // 服务端须要在响应头设置 Content-Disposition
const blob = new Blob([res.data], {
type: 'application/octet-stream',
});
const linkNode = document.createElement('a');
linkNode.download = filename;
linkNode.style.display = 'none';
linkNode.href = URL.createObjectURL(blob);
document.body.appendChild(linkNode);
linkNode.click();
URL.revokeObjectURL(linkNode.href);
document.body.removeChild(linkNode);
} else {
// 导出失败
}
复制代码
nodeJs采用的是egg框架,如下三种请求方式在前期没有没有设置编码的时候均是返回乱码。后续在发现问题点以后通过修改都能成功获取到一个Buffer缓存,直接往浏览器端返回便可。我采用的是axios的方案,无他,就是对这个库比较熟而已,在不一样环境下可能会出现请求响应不一致的状况,这里将三种请求都分享给你们promise
const axios = require('axios');
const rp = require('request-promise');
/** * 方案1 egg内置的curl请求 * 关键配置:不设置dataType属性 * dataType的做用是明确告诉 HttpClient 以 xml等文本 格式处理返回的响应 body,设置为‘json’ ,以 JSON 格 * 式处理返回的响应 body * 不设置dataType:默认 HttpClient 不会作任何处理,会直接返回 Buffer 类型数据 */
const result = await ctx.curl(requestURI, {
method: 'POST',
timeout: 60000,
data: JSON.stringify(body),
});
ctx.set({
'Access-Control-Expose-Headers': 'Content-Disposition',
'content-disposition': result.headers['content-disposition'],
});
ctx.body = result.data;
/** * 方案2 axios * 关键配置: responseType: 'arraybuffer', responseEncoding: 'binary' */
const result = await axios({
method: 'POST',
url,
params: queryParams,
data: body,
responseType: 'arraybuffer',
responseEncoding: 'binary',
});
ctx.set({
'Access-Control-Expose-Headers': 'Content-Disposition',
'content-disposition': result.headers['content-disposition'],
});
ctx.body = result.data;
/** * 方案3 request-promise * 关键配置: encoding: null, * 设置encoding为binary仍是会乱码,后续发如今stack overflow上发现设置为null能解决问题 * address:https://stackoverflow.com/questions/48752822/request-promise-download-pdf-file/48753392#48753392 */
const result = await rp({
method: 'POST',
uri: requestURI,
body: JSON.stringify(body),
resolveWithFullResponse: true,
encoding: null,
});
ctx.set({
'Access-Control-Expose-Headers': 'Content-Disposition',
'content-disposition': result.headers['content-disposition'],
});
ctx.body = result.body;
复制代码
谨以此文,记念这次开发导出Excel功能中遇到的问题浏览器
路漫漫其修远兮,吾将上下而求索