需求
nodejs 作为中间层提供接口转发,后端已提供 http 下载接口,node 层通过 axios 调用后端接口,并转发给前端。
当下载小文件时,无问题。
下载大文件(几十 M)时,会出现一直 loading 的截图。

分析
一开始怀疑后端接口本身有问题,替换成页面直接调用后端接口,表现如下:
立马出现下载弹窗; 点击下载后,浏览器关闭页面,进行下载,但是下载看上去是断点连续的。
通过抓包工具看到,直接调用后端的接口,发现返回头里有一条:
Transfer-Encoding:chunked
那么问题来了:
- node 通过 axios 请求后端接口时,是通过 await 这个请求,等请求全部返回后才返回给前端的;如何在 axios 里做到边接收边返回;或者直接不使用 axios;
- node 返回给前端时怎样做到 chunked?(这个大体能想到思路,通过 stream 流式获取后端数据,再不断的 pipe 给 res)
解决方式
axios 支持流式传输,

效果
不再一直阻塞,而是立马打开一个下载的弹窗,确认后,开始流式下载。

总结
其实,对于大数据量的接口,node 中间层不适合转发这类请求。更合理的做法是,由后端将下载文件上传到云(如 s3),前端通过异步轮询拿到一个云返回的下载链接,这种方式可以降低网络抖动造成的中断,且云文件系统的下载一般都支持了断点续传。