浅析Node.js实现HTTP文件下载


Posted in Javascript onAugust 05, 2016

前言

HTTP实现文件下载时,只要在服务器设置好相关响应头,并使用二进制传输文件数据即可,而客户端(浏览器)会根据响应头接收文件数据。而在Node.js中,设置好响应头后,读取文件流,再使用“.pipe()”方法将流转接到响应对象Response就可以实现一个简单的文件下载服务器。

1. 文件下载介绍

HTTP基于请求头和响应头实现状态交互,在得到服务器正确响应状态后,而客户端首先会解析响应头,并根据响应头来接收和展示数据(响应体)。对于文件下载来说,其实现过程如下:

    1.客户端发起文件资源请求

    2.服务器查找对应文件,并设置”Content-Type”、”Content-Disposition”等响应头,分别用于表示文件的”MIME”类型及文件描述

    3.客户端根据服务器返回的响应头解析和接收文件数据

需要设置的响应头

设置文件下载响应头时,除了常用的HTTP响应头外,比较重要是还要设置以下两个响应头:

Content-Type: application/octet-stream
Content-Disposition: attachment; filename=MyFileName.ext

在上面的设置中,”Content-Type: application/octet-stream”告诉浏览器这是一个二进制文件,”Content-Disposition”告诉浏览器这是一个需要下载的附件并告诉浏览器默认的文件名。如果不添加”Content-Disposition”响应头,浏览器可能会下载或显示文件内容,不同浏览器的处理有所不同。

2. Node.js文件下载服务器实现

接下来我们基于Express 框架实现一个简单文件下载服务器,在这个服务器中主要包括两个功能:服务器文件的浏览文件的下载

2.1 添加路由

创建Express应用后,添加如下两个路由:

router.get('/files', function(req, res, next) {
 // 显示服务器文件 
});
router.get('/file/:fileName', function(req, res, next) {
 // 实现文件下载 
});

上面的添加的两个路由分别用于:显示服务器文件、实现文件下载

2.2 显示服务器文件

实现服务器文件的显示,要通过”fs”模块读取文件目录并进行文件/目录检查等。还需要使用”path”模块处理文件路径。首先引入这两个模块:

const fs = require('fs');
const path = require('path');

显示服务器文件实现代码如下:

router.get('/files', function(req, res, next) {
 // 显示服务器文件 
 // 文件目录
 var filePath = path.join(__dirname, './');
 fs.readdir(filePath, function(err, results){
  if(err) throw err;
  if(results.length>0) {
   var files = [];
   results.forEach(function(file){
   if(fs.statSync(path.join(filePath, file)).isFile()){
     files.push(file);
   }
   })
   res.render('files', {files:files});
  } else {
   res.end('当前目录下没有文件');
  }
 });
});

上面代码中,读取目录后通过视图文件”files.ejs”显示可下载文件列表。其代码如下:

<!DOCTYPE html>
<html>
 <head>
  <title>下载文件选择</title>
 </head>
 <body>
  <h1>请选择下载文件:</h1>
  <% if(files.length>0) {%>
  <ul>
   <% files.forEach(function(file){ %>
   <li>
    <a href="/file/<%- file %>" target="_blank"><%- file %></a>
   </li>
   <%})%>
  </ul>
  <%} else {%>
  <p>没有可下载文件…</p>
  <%}%>
 </body>
</html>

2.3 实现文件下载

实现文件下载时,可以先读取文件到一个”Buffer”中,再通过”res.send()”或”res.end()”方法发送文件数据,也可以基于流(”Stream”)实现文件数据的发送。使用”Stream”实现文件下载时,可以使用”fs.createReadStream()”方法创建一个可读流,而响应对象Response是一个可写流。这样,只需要通过”.pipe()”方法将文件流转接到Response响应流中即可。

文件下载实现代码如下:

router.get('/file/:fileName', function(req, res, next) {
 // 实现文件下载 
 var fileName = req.params.fileName;
 var filePath = path.join(__dirname, fileName);
 var stats = fs.statSync(filePath); 
 if(stats.isFile()){
  res.set({
   'Content-Type': 'application/octet-stream',
   'Content-Disposition': 'attachment; filename='+fileName,
   'Content-Length': stats.size
  });
  fs.createReadStream(filePath).pipe(res);
 } else {
  res.end(404);
 }
});

总结

以上就是利用Node.js实现HTTP文件下载的全部内容,希望对大家学习Node.js有所帮助。

Javascript 相关文章推荐
用roll.js实现的图片自动滚动+鼠标触动的特效
Mar 18 Javascript
jquery动态加载select下拉框示例代码
Dec 10 Javascript
javascript分页代码实例分享(js分页)
Dec 13 Javascript
javascript图片预加载完整实例
Dec 10 Javascript
JavaScript弹出对话框的三种方式
Mar 23 Javascript
jQuery中$.each()函数的用法引申实例
May 12 Javascript
js放大镜放大购物图片效果
Jan 18 Javascript
微信小程序商城项目之侧栏分类效果(1)
Apr 17 Javascript
React Native使用百度Echarts显示图表的示例代码
Nov 07 Javascript
JS实现简单的文字无缝上下滚动功能示例
Jun 22 Javascript
详解Vue 项目中的几个实用组件(ts)
Oct 29 Javascript
在vue中使用image-webpack-loader实例
Nov 12 Javascript
JS中对Cookie的操作详解
Aug 05 #Javascript
jQuery插件EasyUI获取当前Tab中iframe窗体对象的方法
Aug 05 #Javascript
js实现精确到毫秒的倒计时效果
Aug 05 #Javascript
jQuery实现Select左右复制移动内容
Aug 05 #Javascript
jQuery插件EasyUI实现Layout框架页面中弹出窗体到最顶层效果(穿越iframe)
Aug 05 #Javascript
jQuery插件EasyUI设置datagrid的checkbox为禁用状态的方法
Aug 05 #Javascript
基于HTML+CSS+JS实现增加删除修改tab导航特效代码
Aug 05 #Javascript
You might like
php对数组排序代码分享
2014/02/24 PHP
php利用curl抓取新浪微博内容示例
2014/04/27 PHP
php实现的简单检验登陆类
2015/06/18 PHP
CodeIgniter自定义控制器MY_Controller用法分析
2016/01/20 PHP
PHP实现数组向任意位置插入,删除,替换数据操作示例
2019/04/05 PHP
PHP中遍历数组的三种常用方法实例分析
2019/06/24 PHP
ExtJS 下拉多选框lovcombo
2010/05/19 Javascript
浅谈Javascript嵌套函数及闭包
2010/11/09 Javascript
利用JQuery和JS实现奇偶行背景颜色自定义效果
2012/11/19 Javascript
jquery实现的可隐藏重现的靠边悬浮层实例代码
2013/05/27 Javascript
JS cookie中文乱码解决方法
2014/01/28 Javascript
JS判断两个时间大小的示例代码
2014/01/28 Javascript
Javascript中3种实现继承的方法和代码实例
2014/08/12 Javascript
PHP 数组current和next用法分享
2015/03/05 Javascript
JS实现带提示的星级评分效果完整实例
2015/10/30 Javascript
node.js连接mongoDB数据库 快速搭建自己的web服务
2016/04/17 Javascript
微信小程序 教程之注册页面
2016/10/17 Javascript
Ajax跨域实现代码(后台jsp)
2017/01/21 Javascript
JavaScript的for循环中嵌套一个点击事件的问题解决
2017/03/03 Javascript
详解react-router 4.0 下服务器如何配合BrowserRouter
2017/12/29 Javascript
详解使用vue-cli脚手架初始化Vue项目下的项目结构
2018/03/08 Javascript
配置一个vue3.0项目的完整步骤
2019/04/26 Javascript
[52:39]完美世界DOTA2联赛PWL S3 CPG vs Forest 第一场 12.16
2020/12/17 DOTA
[02:50]【扭转乾坤,只此一招】DOTA2永雾林渊版本开启新篇章
2020/12/22 DOTA
老生常谈Python进阶之装饰器
2017/05/11 Python
python无序链表删除重复项的方法
2020/01/17 Python
python+Selenium自动化测试——输入,点击操作
2020/03/06 Python
哈萨克斯坦最大的时装、鞋子和配饰在线商店:Lamoda.kz
2019/11/19 全球购物
网页美工求职信范文
2014/04/17 职场文书
小学数学课后反思
2014/04/23 职场文书
违反单位工作制度检讨书
2014/10/25 职场文书
停发工资证明范本
2015/06/12 职场文书
导游词之峨眉乐山/兵马俑/北京故宫御花园
2019/09/03 职场文书
golang中的并发和并行
2021/05/08 Golang
MySQL表锁、行锁、排它锁及共享锁的使用详解
2022/04/02 MySQL
python DataFrame中stack()方法、unstack()方法和pivot()方法浅析
2022/04/06 Python