浅析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 相关文章推荐
Javascript Select操作大集合
May 26 Javascript
dotopAlert 提示用户需安装播放器的代码
Sep 17 Javascript
Enter转换为Tab的小例子(兼容IE,Firefox)
Nov 14 Javascript
Jquery原生态实现表格header头随滚动条滚动而滚动
Mar 18 Javascript
JS判断变量是否为空判断是否null
Jul 25 Javascript
jqueryMobile使用示例分享
Jan 12 Javascript
javascript事件绑定学习要点
Mar 09 Javascript
Node.js+Express配置入门教程
May 19 Javascript
关于vue利用postcss-pxtorem进行移动端适配的问题
Nov 20 Javascript
浅析JavaScript预编译和暗示全局变量
Sep 03 Javascript
js+audio实现音乐播放器
Sep 13 Javascript
JS+CSS实现过渡特效
Jan 02 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程序员最常犯的11个MySQL错误小结
2010/11/20 PHP
PHP+Mysql日期时间如何转换(UNIX时间戳和格式化日期)
2012/07/15 PHP
PHP中的排序函数sort、asort、rsort、krsort、ksort区别分析
2014/08/18 PHP
Yii2 rbac权限控制操作步骤实例教程
2016/04/29 PHP
PHP实现的统计数据功能详解
2016/12/06 PHP
php爬取天猫和淘宝商品数据
2018/02/23 PHP
js+css实现增加表单可用性之提示文字
2013/06/03 Javascript
sencha touch 模仿tabpanel导航栏TabBar的实例代码
2013/10/24 Javascript
js中使用replace方法完成某个字符的转换
2014/08/20 Javascript
jQuery中noConflict()用法实例分析
2015/02/08 Javascript
JavaScript自定义数组排序方法
2015/02/12 Javascript
基于JavaScript实现移动端点击图片查看大图点击大图隐藏
2015/11/04 Javascript
基于BootStarp的Dailog
2016/04/28 Javascript
Bootstrap优化站点资源、响应式图片、传送带使用详解3
2016/10/14 Javascript
Bootstrap CSS布局之表单
2016/12/17 Javascript
jQuery使用unlock.js插件实现滑动解锁
2017/04/04 jQuery
Bootstrap Table 删除和批量删除
2017/09/22 Javascript
vue底部加载更多的实例代码
2018/06/29 Javascript
微信小程序之自定义组件的实现代码(附源码)
2018/08/02 Javascript
vue 解决computed修改data数据的问题
2019/11/06 Javascript
详解一些适用于Node.js的命名约定
2019/12/08 Javascript
JavaScript实现轮播图效果
2020/10/30 Javascript
[04:44]DOTA2西游记战队视频彩蛋流出 师徒开黑巧遇林书豪
2016/08/03 DOTA
[01:00:35]2018DOTA2亚洲邀请赛3月30日B组 EffcetVSMineski
2018/03/31 DOTA
Python中使用插入排序算法的简单分析与代码示例
2016/05/04 Python
基于python批量处理dat文件及科学计算方法详解
2018/05/08 Python
python字符串替换re.sub()方法解析
2019/09/18 Python
命令行运行Python脚本时传入参数的三种方式详解
2019/10/11 Python
Python基础之高级变量类型实例详解
2020/01/03 Python
美国皮靴公司自1863年:The Frye Company
2016/11/30 全球购物
法国在线药房:Shop Pharmacie
2019/11/26 全球购物
教育实习生的自我评价分享
2013/11/21 职场文书
2015年信息技术教研组工作总结
2015/07/22 职场文书
小学生一年级(书信作文)
2019/08/13 职场文书
三好学生竞选稿范文
2019/08/21 职场文书
nginx 添加http_stub_status_module模块
2022/05/25 Servers