nodejs上传文件和下载文件到本地(二)——下载文件到本地篇

上次讲完了上传的部分,今天来说说下载的部分,下载可是坑了我不少,下载的文件名一直是中文乱码,内容倒是很正常。

包的管理还是用一个表格来呈现,把上一个包管理的删除按钮功能换成下载功能即可

文件下载和上传不同,不需要传路径地址什么的,其实请求都可以很随意,如果不是为了区分是什么文件,在前段页面只需要做一件事发一个请求,只需要简单的一句话就行

function downloadPackage(productType,packageName) {
            var url = "http://" + window.location.host + "/fxrest/downloadPackage/"+productType+"/" + packageName;
            console.log("url:" + url);
            window.location.href = url;
        }

就是它,只需要执行windows.location.href = url,定向一个地址即可,系统会发一个get请求给后台服务器

后台解析的部分则按照get请求传参数的方式来解析

router.get('/downloadPackage/:productType/:packageName',function (req, res) {
    var productType = req.params.productType;
    var packageName = req.params.packageName;
    loginService.downloadPackage(productType,packageName,req,res,function (data) {
        console.info("下载结果:"+data);
    })
});

然后执行文件下载的方法

module.exports.downloadPackage = function (productType, packageName, req, res, cb) {
    //开始下载文件
    fileDownloadDao.getFilePath(productType, packageName, function (err, data) {
        console.log("vals:" + JSON.stringify(data));
        try {
            if (JSON.stringify(data).length != "2") {
                downloadTimes = data[0].downloadTimes + 1;
                //文件名称
                var name = packageName;
                //文件路径
                var path = data[0].uploadPath;
                //文件大小
                var size = fs.statSync(path).size;
                //判断浏览器,设置回复头信息,这里一定要设置,否则下载文件名会乱码
                var userAgent = (req.headers['user-agent']||'').toLowerCase();
                if(userAgent.indexOf('msie') >= 0 || userAgent.indexOf('chrome') >= 0) {
                    //如果是msie浏览器,文件名转码方式
                    res.setHeader('Content-Disposition', 'attachment; filename=' + encodeURIComponent(name));
                } else if(userAgent.indexOf('firefox') >= 0) {
                    //如果是火狐浏览器,文件名转码方式
                    res.setHeader('Content-Disposition', 'attachment; filename*="utf8\'\'' + encodeURIComponent(name)+'"');
                } else {
                    /* safari等其他非主流浏览器只能自求多福了 */
                    res.setHeader('Content-Disposition', 'attachment; filename=' + new Buffer(name).toString('binary'));
                }
                //设置头信息下载类型为二进制文件,且为utf-8的编码格式
                res.setHeader('Content-Type', 'application/octet-stream;charset=utf8');
                //设置头信息文件大小
                res.setHeader('Content-Length', size);
                //获取文件流
                var stream = fs.createReadStream(path);
                //将文件流用回复管道推出去
                stream.pipe(res);
                stream.on('close', function () {
                    cb("下载完成:"+name);
                });
            } else {
                cb("err");
            }
        } catch (e) {
            console.error("下载升级包失败:" + e);
        }
        if (err) {
            console.log("查询升级包地址失败:" + err);
        }
        console.log("downloadTimes:"+downloadTimes);
        fileDownloadDao.updataDowntimes(downloadTimes,productType,packageName,function (err, vals) {
            if (err) {
                console.log("更新下载次数失败:" + err);
            }
        });
    });
};

设置头信息的时候,一定要注意格式,就这个地方,我查了很久的资料,也试过很多人的很多方法,都没有效果

其实

res.setHeader('Content-Disposition', 'attachment; filename*="utf8\'\'' + encodeURIComponent(name)+'"');

这只这一句话,在火狐和谷歌浏览器上,文件名都是不会乱码的,这里就完美的完成了我的这一次任务啦。

具体项目代码,可以去我的git上,附上我的git地址:https://github.com/Duplicity1/upgradeServer


版权声明:本文为CSDN_xiaoxiaocainiao原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。