需求背景
在一个奇葩的项目中。开发公众号用koa处理。对于接口则进行转发到.net的框架后端。因此在一个新需求中对于需要上传文件中没有处理。维护的人提桶了。因此在处理中发现了一点点问题
代码分析
const bodyparser = require('koa-bodyparser')
app.use(bodyparser())
const response = await axios.post(targetUrl + requestPath, body , { headers:{
timeout:600*1000,
license,
'Content-Type': 'application/json; charset=utf-8',
} });
// 将目标服务器的响应转发给客户端
ctx.status = response.status;
ctx.body = response.data;
在对请求中只处理一种方式。就是普通的post请求,但是公司是查看附件是通过流的形式返回。上传是通过formData的方式处理。因此思考过后需要再添加2种方式来转发。对应上传与查看
上传附件的请求改造
- koa-bodyparser并不支持关于formData的接收
- 原先的Content-Type:application/json也需要处理成multipart/form-data
处理方式
- 引入koa-body支持文件信息
- 引入form-data模板浏览器的formData传输;
- 处理Content-Type
koa-body的接收参数ctx.request如下
处理代码如下
const formData = new FormData();
const fields = ctx.request.body;
const files = ctx.request.files;
// 将普通字段添加到新的 FormData 中
Object.keys(fields).forEach((key) => {
formData.append(key, fields[key]);
});
//将文件信息添加到新的FormData 中
Object.keys(files).forEach((key) => {
formData.append(key,fs.createReadStream(files[key].path),files[key].name);
})
// 发起转发请求
const license = headers.license || null;
const response = await axios({
method: 'POST',
url: targetUrl + requestPath,
headers: {
license,
'Content-Type':'multipart/form-data'
},
timeout:600*1000,
data:formData,
// headers: formdata.getHeaders(),
查看上传附件的请求改造
- node的环境不支持responseType:blob,
原因如下
-
Node.js 环境:
Blob
是浏览器环境中的一种数据类型,它在服务器端的 Node.js 中原生并不支持。因此,如果你在 Koa 服务器上转发请求,直接使用blob
会导致兼容性问题,因为 Node.js 没有对Blob
的内建支持。 -
浏览器环境:如果你是在浏览器中执行这段代码,使用
blob
作为responseType
是可行的,浏览器会直接处理并返回Blob
对象。 -
arraybuffer特性: 是一种通用的二进制数据格式,它既适用于 Node.js 环境,也适用于浏览器环境。因为
Blob
不能直接用于 Node.js,使用arraybuffer
可以在接收到二进制数据后,根据需要将其转换为Blob
,这样你的代码可以同时兼容浏览器和服务器端。 -
arraybuffer灵活性:使用
arraybuffer
后,你可以根据需要将其转化为其他数据类型。例如,如果你需要将数据传输给前端并希望前端处理为Blob
,可以在服务器端使用arraybuffer
获取数据,然后再通过Buffer
转化或直接传输给前端,由前端将其转换为Blob
。
处理方式
responseType:arraybuffer
处理代码如下
try {
// 发起转发请求
const response = await axios({
url:targetUrl + requestPath ,
method:"GET",
responseType: 'arraybuffer', // 使用 'arraybuffer' 来处理二进制数据
headers: {
license,
'Content-Type': 'application/json', // 或者根据需求设置合适的内容类型
}
},);
// 将目标服务器的响应转发给客户端
ctx.status = response.status;
// 将 arraybuffer 转换为 Buffer 以适应 Koa
ctx.body = Buffer.from(response.data);
// 设置响应头中的内容类型,保持与目标服务器一致
ctx.set('Content-Type', response.headers['content-type']);
} catch (error) {
ctx.status = 500;
ctx.body = 'Internal Server Error';
console.error(error);
}