node文件下载的方式

node文件下载主要有两种方式,第一种就是原生的设置请求头的content-type 与 Content-Disposition来告诉浏览器,响应结果属于文件下载,准备好接收文件;第二种是使用express框架自带的下载api。

1. 设置响应头的方式

这里需要补充一下,http文件下载的知识。文件下载其实就是通过设置响应头的响应内容和行为,然后将数据流放入到响应体中,浏览器读取响应头的时候,得知这是什么类型的文件数据,浏览器会整理并打开自己的保存下载文件机制。

这里贴上各种文件的传输content-type查询链接:https://tool.oschina.net/commons

案例展示: 我需要下载test.txt文件

  1. 首先在route中提供文件下载的api

    app.route('/download').get(TestController.download);
    
  2. 在TestController中实现download方法,特别要注意响应头的content-type的设置,不同的文件类型会是不一样的content-type,可以根据上面的链接进行查询。

    const download = async(req, res) => {
        // 第一步,先获取文件的buffer字节流,这里具体做了什么,看第三步
        let {fileName, buffer} = await TestService.download();
        res.setHeader('Content-Type', 'application/octet-stream');
        res.setHeader('Content-Disposition', `attachment;filename=${fileName}`);
        res.status(200).send(buffer);
    }
    
  3. 实现TestService的download方法

    const download = () => {
      let filePath = '/test.txt';
      let buffer = fs.readFileSync(filePath);
      let fileName = path.basename(filePath);
      return {fileName, buffer};
    }
    
  4. 到这里,后端文件下载部分就完成了,如果你是通过超链接,点击一下就下载的话,可以顺利地去触发浏览器的默认下载行为,你的浏览器应该就会提示你正在下载了。如果你不是通过a标签,而是通过ajax或者axios的话,这时候需要前端再去通过超链接或者ifram去访问后端,触发浏览器的默认下载行为。

    若有需要,可以参考这篇文章:https://blog.csdn.net/interestANd/article/details/121855311

2. 通过express框架的download api去实现文件下载

​ 用这个的话,相对第一种方式就省事很多,他会帮我们把文件读取转换成二进制流,而且不需要我们设置响应头等信息,也能实现同样的效果。

res.download(path, [filename], [fn])

path所需传输附件的路径, 通常情况下浏览器会弹出一个下载文件的窗口。 浏览器弹出框里的文件名和响应头里的Disposition “filename=” 参数是一致的, 你也可以通过传入filename来自由设置。

当在传输的过程中发生一个错误时,可选的回调函数fn会被调用执行。 这个方法使用res.sendfile()传输文件。

res.sendfile(path, [options], [fn]])

path所传输附件的路径。

它会根据文件的扩展名自动设置响应头里的Content-Type字段。 回调函数fn(err)在传输完成或者发生错误时会被调用执行。

Options:

  • maxAge 毫秒,默认为0
  • root 文件相对的路径

这个方法可以非常良好的支持有缩略图的文件服务。

参考代码:

主要区别是在于controller层,其余的代码一致,不过由于我的这个案例需求实在是太简单了,就省略service层不做了。

const download = async (req, res) => {
  try {
    let filePath = '/test.txt';
    let fileName = path.basename(filePath);
    res.download(filePath, fileName);
  } catch (error) {
    return res.status(500).send({
      result: 'error',
      message: `Failed to download file: ${error.message}`
    })
  }
}
  • 1
    点赞
  • 5
    收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:精致技术 设计师:CSDN官方博客 返回首页
评论 1

打赏作者

InterestAndFun

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值