浅析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 相关文章推荐
IE autocomplete internet explorer's autocomplete
Jun 30 Javascript
Javascript中的变量使用说明
May 18 Javascript
基于javascript实现泡泡大冒险网页版小游戏
Mar 23 Javascript
基于BootStrap的Metronic框架实现页面链接收藏夹功能按钮移动收藏记录(使用Sortable进行拖动排序)
Aug 29 Javascript
浅谈JS之tagNaem和nodeName
Sep 13 Javascript
js将字符串中的每一个单词的首字母变为大写其余均为小写
Jan 05 Javascript
JavaScript校验Number(4,1)格式的数字实例代码
Mar 13 Javascript
JS设计模式之数据访问对象模式的实例讲解
Sep 30 Javascript
解决在vue项目中webpack打包后字体不生效的问题
Sep 01 Javascript
微信小程序常见页面跳转操作简单示例
May 01 Javascript
layui table单元格事件修改值的方法
Sep 24 Javascript
解决vue自定义组件@click点击失效问题
Apr 30 Vue.js
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实现的网络相册图片防盗链完美破解方法
2015/07/01 PHP
PHP 7.0.2 正式版发布
2016/01/08 PHP
laravel框架实现去掉URL中index.php的方法
2019/10/12 PHP
laravel 解决Validator使用中出现的问题
2019/10/25 PHP
如何在centos8自定义目录安装php7.3
2019/11/28 PHP
JavaScript 开发规范要求(图文并茂)
2010/06/11 Javascript
JSP跨iframe如何传递参数实现代码
2013/09/21 Javascript
jquery $.fn $.fx是什么意思有什么用
2013/11/04 Javascript
分享JavaScript获取网页关闭与取消关闭的事件
2013/12/13 Javascript
js与jquery获取父级元素,子级元素,兄弟元素的实现方法
2014/01/09 Javascript
nodejs教程之环境安装及运行
2014/11/21 NodeJs
JavaScript脚本判断蜘蛛来源的方法
2015/09/22 Javascript
详解js跨域原理以及2种解决方案
2015/12/09 Javascript
一个字符串中出现次数最多的字符 统计这个次数【实现代码】
2016/04/29 Javascript
javascript简单实现等比例缩小图片的方法
2016/07/27 Javascript
基于jQuery实现仿微博发布框字数提示
2016/07/27 Javascript
Bootstrap CSS组件之按钮组(btn-group)
2016/12/17 Javascript
快速解决brew安装特定版本flow的问题
2018/05/17 Javascript
深入浅析Node环境和浏览器的区别
2018/08/14 Javascript
Koa 使用小技巧(小结)
2018/10/22 Javascript
详解Vue调用手机相机和相册以及上传
2019/05/05 Javascript
layui添加动态菜单与选项卡 AJAX请求的例子
2019/09/25 Javascript
jquery实现上传图片功能
2020/06/29 jQuery
python动态参数用法实例分析
2015/05/25 Python
python迭代器与生成器详解
2016/03/10 Python
python图形开发GUI库pyqt5的基本使用方法详解
2020/02/14 Python
Python 爬虫的原理
2020/07/30 Python
HTML5 canvas画图并保存成图片的jcanvas插件
2014/01/17 HTML / CSS
详解HTML5中表单验证的8种方法介绍
2016/12/19 HTML / CSS
十八届三中全会学习方案
2014/02/16 职场文书
房产委托公证书样本
2014/04/04 职场文书
领导班子专题民主生活会情况想汇报
2014/09/30 职场文书
摘录式读书笔记
2015/07/01 职场文书
离婚起诉书范文2016
2015/11/26 职场文书
详细总结Python常见的安全问题
2021/05/21 Python
pytorch中F.avg_pool1d()和F.avg_pool2d()的使用操作
2021/05/22 Python