专栏首页OECOM使用nodejs做文件下载中转

使用nodejs做文件下载中转

之前做了一个功能就是点击按钮实现文件下载,文件保存在了阿里云的OSS上,阿里的OSS和七牛的OSS其实个人感觉差不多,一般情况下,前端下载文件很多都是通过一个a标签来进行下载。但是对于OSS存储的文件比如图片点击后在浏览器直接打开了,即使是添加了download属性也无济于事,于是我就想到了使用nodejs来搭建一个中转站。

我们先来直接看一下示例代码,然后再进行说明:

router.get('/downloadFile',function(req,res){
    try{
        let filePath = req.query.filePath;
        let fileName = req.query.fileName;
        let imgProtocol = filePath.slice(0,filePath.indexOf(":"));
        let imgName = fileName||filePath.slice(filePath.lastIndexOf("/")+1);
        if(imgProtocol==='https'){
            https.get(filePath,function(imgReq,imgRes){  //path为网络文件地址
                var fileSize = imgReq.headers["content-length"];
                imgReq.setEncoding('binary');
                res.setHeader("Content-Type", "application/octet-stream");
                res.setHeader("content-length",fileSize);
                res.setHeader("Content-Disposition", "attachment; filename="+encodeURI(imgName));
                res.setTimeout(30*60*1000)
                imgReq.on('data',function(chunk){
                    res.write(chunk,"binary"); //格式必须为 binary,否则会出错
                })
                imgReq.on('end',function(){
                    console.log("文件下载完毕");
                    res.end()
                })
            })
        }else{
            http.get(filePath,function(imgReq,imgRes){  //path为网络文件地址
                var fileSize = imgReq.headers["content-length"];
                imgReq.setEncoding('binary');
                res.setHeader("Content-Type", "application/octet-stream");
                res.setHeader("content-length",fileSize);
                res.setHeader("Content-Disposition", "attachment; filename="+encodeURI(imgName));
                res.setTimeout(30*60*1000)
                imgReq.on('data',function(chunk){
                    res.write(chunk,"binary"); //格式必须为 binary,否则会出错
                })
                imgReq.on('end',function(){
                    console.log("文件下载完毕");
                    res.end()
                })
            })
        }
    }catch(e){
        res.end(JSON.stringify({success: false, msg: e.stack}));
    }

})

从上面的代码中我们可以看到,接口接收的参数有两个,一个是文件名,一个是文件路径,如果没有文件名我们就默认文件路径的最后一个斜杠后面就是文件名了。接下来要做的就是区分文件存储的环境是https还是http,两种方式没有什么别的区别,只是请求的模块不一样,当然这里我们也可以使用request模块,不在多说。当get请求有响应后,我们开始做向客户端返回数据的准备。

如上面代码中所示,我们获取了content-length,来告诉客户端浏览器将要下载的文件总大小是多少。然后设置文件的编码为binary,也就是二进制的格式,为什么要设置成二进制呢?是因为我们不知道即将下载的文件格式具体是什么。所以我们也将Content-Type的内容设置成了application/octet-stream。随后设置的就是文件大小和Content-Disposition,在这里我们对filename进行了url转码,是因为如果直接使用中文,在这里会报错的。

再后面我们设置了一个超时时间为30分钟,因为nodejs默认的接口超时时间为2分钟,这对于下载一些大文件来说很不现实。我设置30分钟是因为这里文件的大小不超过200M,30分钟足矣下载完成,当然,你也可以设置为setTimeout(0),使其超时时间不做限制。

随后当请求返回数据后,我们也将数据写入到接口的响应体中,同时编码格式也是二进制。直到流获取完成,此时也将数据全部都写入到了响应体中,之后调用res.end来结束连接。

如此,一个使用nodejs来作为文件下载中转的例子就写好了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • jQueryUI实现自动完成输入框提示

    在昨天我发表了一个jQueryUI的effect方法,下面我再来给大家介绍一个通过jQueryUI来实现自动完成输入框提示的方法。他需要调用jQuery对象的 ...

    无邪Z
  • exports和module.exports介绍

    为了让nodejs开发过程中,为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统,模块是Node.js 应用程序的基本组成部分,文件...

    无邪Z
  • 微信小程序获取用户信息

    在微信小程序中,如果想获取用户的昵称等信息可以不用另外写后台,如果需要获取用户的unionId,则需要后台来提供获取sessionKey和解码encrypted...

    无邪Z
  • Python判断两个单词的相似度

    本文要点在于算法的设计:如果两个单词中不相同的字母足够少,并且随机选择几个字母在两个单词中具有相同的前后顺序,则认为两个单词是等价的。 目前存在的问题:可能会有...

    Python小屋屋主
  • 050|物流自动化的底层技术—上(物料流)

    随着国内近几年来电商的迅猛发展,普通老百姓也能经常在各个媒体平台上看到一些关于大的电商公司后台的物流配送中心里全自动化运作的盛况,比如京东的亚洲一号、菜...

    老King
  • 【适合收藏】为了多点时间陪女朋友,我向BAT大佬跪求了这15条JS技巧

    为了减少加班,从而挤出更多的时间来陪女朋友,我就厚着脸皮向一些BAT大佬求来了这15条JS技巧,现在分享给大家,千万别错过。

    陈大鱼头
  • 【适合收藏】为了多点时间陪女朋友,我向BAT大佬跪求了这15条JS技巧

    为了减少加班,从而挤出更多的时间来陪女朋友,我就厚着脸皮向一些BAT大佬求来了这15条JS技巧,现在分享给大家,千万别错过。

    刘小夕
  • 爬虫课程(二)|PyCharm的安装激活和简单使用

    黄小怪
  • Redis教程02(五大数据类型简介)

    本文给大家介绍下Redis中的五大数据类型 Redis中的数据都是key/value对,这里的数据类型指的是value的值的类型

    用户4919348
  • Github速度太慢全网最全方案

    近日,我在Github上下载源码,真的鸡肋,慢的一匹,通过以下方式,让我下载Github速度飞快,因为刚好有代理,就用的第一种方式,而后面几种方式参考自网上的一...

    公众号guangcity

扫码关注云+社区

领取腾讯云代金券