IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Express の 文件下载 -> 正文阅读

[JavaScript知识库]Express の 文件下载

Express の 文件下载

上一篇谈到了使用express处理POST请求。

文件下载

简单粗暴,下载文件就用res.download()方法。(💊这个方法只能在 v4.16.0 之后使用…)

app.get('/download/:type', (req, res) => {
  let type = req.params.type || '';
  console.log(type);
  if (type === 'pdf') {
    res.download('C:/Users/lenovo/Desktop/if.pdf');
  } else if (type === 'image') {
    res.download('C:/Users/lenovo/Pictures/love.jpg');
  } else {
    res.download('../resource/index.html');
  }
});

在这里插入图片描述

有几点需要注意的地方🤔

  • 绝对路径或相对路径都可以。这不同res.sendFile()方法,后者只能使用绝对路径。
  • windows 下目录分隔符是\,但是这里要使用/

这个方法其实还有其他参数,比如指定下载的文件名。

app.get('/download/:type', (req, res) => {
  let type = req.params.type || '';
  console.log(type);
  if (type === 'pdf') {
    res.download('C:/Users/lenovo/Desktop/if.pdf', '如果.pdf');
  } else if (type === 'image') {
    res.download('C:/Users/lenovo/Pictures/love.jpg', '爱.jpg');
  } else {
    res.download('../resource/index.html', '首页.html');
  }
});

在这里插入图片描述
如果代码加上不生效,试试浏览器禁用缓存…(别问我怎么知道的😅)
再来,就是指定传输完成或发生异常时的回调函数

app.get('/download/:type', (req, res) => {
  let type = req.params.type || '';
  console.log(type);
  if (type === 'pdf') {
    res.download('C:/Users/lenovo/Desktop/if.pdf', '如果.pdf');
  } else if (type === 'image') {
  	// 回调函数
    res.download('C:/Users/lenovo/Pictures/love.jpg', '爱.jpg', (err) => {
      if (err) {
        console.log('下载内容出错', err);
      } else {
        console.log('传输完成');
      }
    });
  } else {
    res.download('../resource/index.html', '首页.html');
  }
});

没有 v4.16.0 怎么办???

老兄劝你早点升级…(狗头
其实看download方法的官方文档,作者说的很清楚,download内部使用res.sendFile()实现的,后者从 v4.8.0 支持的,如果你连 v4.8.0 也没有,听说隔壁SpringBoot还在支持Java 8,嗯~ o( ̄▽ ̄)o

res.sendFile()自动根据文件的扩展名设置Content-Type响应头。我们先尝试使用上面的绝对文件路径发送文件。

app.get('/file1', (req, res) => {
  res.sendFile('C:/Users/lenovo/Pictures/love.jpg');
});

效果是图片直接展示在浏览器窗口
在这里插入图片描述
为什么会这样我们稍后再说。有一个值得思考的问题,如果我们提供很多个不同下载文件的接口,这些文件都是用绝对路径表示,维护起来就很难受,因为要多处修改。所以sendFile()提供了其他第二个参数options

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

options表示一个对象,其中有一个root属性。如果调用函数时没有root那就必须将path写成绝对路径的形式;如果指定了rootpath就可以使用相对路径,express会帮我们解析文件的最终位置。整个目录是这样的
在这里插入图片描述

app.get('/file2', (req, res) => {
  console.log(__dirname); // C:\Users\lenovo\Desktop\css\node\express
  let options = {
    root: path.join(__dirname, '../resource')
  };
  res.sendFile('love.jpg', options);
});

首先__dirnameNode.js中当前js文件绝对路径的表示。在代码中我们使用path核心库拼接下载文件的根路径path.join(__dirname, '../resource')。其实…我第一次不是这么写的…

app.get('/file3', (req, res) => {
  console.log(__dirname); // C:\Users\lenovo\Desktop\css\node\express
  let options = {
    root: path.join(__dirname, 'resource')
  };
  res.sendFile('../resource/love.jpg', options);
});

这样写会报错ForbiddenError: Forbidden,虽然官网真的说了可以使用相对路径包括..(虽然我翻车了,但是真的没骗人)在这里插入图片描述
下面我们就说一下,为什么使用sentFile()文件直接展示在窗口,而不是下载?

内容协商

内容协商我自己觉得是个很大的内容,说实话在研究上面这个问题之前,我竟然毫不知内容协商是干嘛的,以后再也不说我要转前端了…

在 HTTP 协议中,内容协商是这样一种机制,通过为同一 URI 指向的资源提供不同的展现形式,可以使用户代理选择与用户需求相适应的最佳匹配. – MDN 官网

如果用人话来说,可以简单理解成,假如浏览器通过 URL 请求一段文字,服务端向英语用户返回英文,向中文用户返回中文,这样一个网络资源(文字)就只对应一个 URL。服务端怎么这么智能呢?那是因为浏览器请求时会发送一系列Accept的请求头;浏览器咋知道是英文还是中文呢?那是因为响应包括一系列Content的响应头。(下图来自 MDN 官网)
在这里插入图片描述
用我们上面例子来说,图片没有直接下载而是展示在窗口,就是响应头Content-Disposition捣的鬼😕

Content-Disposition告诉浏览器返回给你的内容究竟如何展示

  • inline: 作为网页的一部分直接展示在浏览器(默认)
  • attachment: 作为 附件 直接下载。后面可以加上; filename=指定下载的文件名。

因为默认属性是inline,所以图片直接展示了,这个功能是不是有点熟悉,没错,一般浏览器对着图片右键就会出现在新标签页中打开图片的选项…就可以这样做
在这里插入图片描述

在这里插入图片描述
那接下来我们修改代码,即可做到使用sendFile()下载文件。

app.get('/file4', (req, res) => {
  res.setHeader('Content-Type', 'image/jpeg');
  // res.setHeader('Content-Disposition', 'inline');
  res.setHeader('Content-Disposition', 'attachment; filename="loveBySendFile.jpg"');
  res.sendFile('C:/Users/lenovo/Pictures/love.jpg');
});

在这里插入图片描述
好了,下载文件就这么多吧,十一放假在家学习效率莫名地高,祝大家节日快乐(不要问我为什么一会用 Edge,一会用 Google 浏览器,一会儿又用 FireFox,问就是我还有 Opera 没用呢😀,其实是不好截图,尤其是下载文件部分。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-03 17:00:20  更:2021-10-03 17:01:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:34:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码