node服务器使用pipe将文件流发送到前端,前端应如何接收

如题,在node端将文件转化为文件流并通过pipe转给res后,前端按照查阅的资料,配置xhr,但是收到的response打印出来size为0;
node端get接口代码如下:

app.get('/api/download',function(req, res, next){
        var currDir = path.join(__dirname,req.query.dir),
            fileName = req.query.name,
            currFile = path.join(currDir,fileName),
            stats = fs.statSync(currFile);
        fs.exists(currFile,function(exist) {
            if(exist){
                res.set({
                    "Content-type":"application/octet-stream",
                    "Content-Disposition":"attachment;filename="+encodeURI(fileName),
                    'Content-Length': stats.size
                });
                let fReadStream = fs.createReadStream(currFile);
                fReadStream.pipe(res);
            }else{
                res.set("Content-type","text/html");
                res.send("file not exist!");
                res.end();
            }
        });
    });

前端接收返回关键代码如下:

                        var xhr = new XMLHttpRequest();    
                        xhr.open("get", '/api/download?dir='+response.data.dir+'&name='+response.data.fileName, true);
                        xhr.responseType = "blob";
                        xhr.onload = function() {
                            if (this.status == 200) {
                                var blob = this.response;
                                console.log(blob);
                    }};
                    xhr.send();

此时前端控制台打印出来的blob为
图片描述

但是如果在node端将pipe注释掉,输入如下代码后,前端便能获得有size的blob。

//fReadStream.pipe(res);
res.send('testtesttesttest')

----------更新线----------

发现问题的一个更深层的表现,直接将拼接好的get方式的url输入浏览器可以直接下载,此时node端获得请求后文件流的size不为0,而通过上文写的xhr请求时,获取的node文件流size为0,也有仔细检查两者输入后获取的文件路径,并没有什么不同,所以就是请求的方式有问题了??

参考链接为:https://www.cnblogs.com/cdemo...

阅读 10.2k
1 个回答

问题结束,自己结帖
首先这两段代码都没有问题,有人会问没有问题你说个鸡儿,报的错哪来的?
别急,应用场景是这样的,全是自己给自己挖的坑

  1. 底层逻辑数据请求接口是由Java写的,也就是说原始文件存在Java服务端
  2. 由于工作需要,前端获取数据操作需要node服务器做中间转发
  3. Java接口使用post方式来请求下载
  4. 最开始没搞清楚怎么用post请求下载,看网上绝大多数都是用get,于是自作主张采用了笨办法:前端点击下载,由node获取参数向Java端post把文件先下载到node并返回前端文件地址和文件名,前端获取到response后拼接成get请求模拟a标签点击去下载node中的文件,下载完成后再将node端对应文件删除。
  5. 所以写到这里自己都忍不住想骂自己蠢,给自己挖坑不说,这样来回请求下载,流量double,真的是败家
  6. 所以问题就出在,第4步的过程是在前端点击下载后完成的,中间没有任何延时等待,请求都是异步的,且node端写好的post/get接口都用了pipe对文件传输做了处理。
  7. 所以前端一点击,node接收到前端请求,向Java端请求数据此时因为pipe所以response里已经有数据且返回,由此前端接收到返回后开始进行拼接get请求url并模拟a标签点击下载,去node端找对应的文件。此时node端里的文件并不一定已经传输完毕,所以此时node里的get请求里获取到的源文件size为0。然后就出现了上述问题。

至于是怎么实现最终的下载,很简单,前端模拟表单进行post请求数据下载,node端的post接口直接将请求到的文件流resFromJava.pipe.(resFromNode)。前端不需要做其他处理就可以出发浏览器的下载事件了。写到这里真的想爆锤自己

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏