浅析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的执行速度
Jan 23 Javascript
javascript针对DOM的应用实例(一)
Apr 15 Javascript
22点关于jquery性能优化的建议
May 28 Javascript
jquery事件preventDefault()方法用法实例
Jan 16 Javascript
JavaScript实现为指定对象添加多个事件处理程序的方法
Apr 17 Javascript
Node.js包管理器Yarn的入门介绍与安装
Oct 17 Javascript
vue.js学习之递归组件
Dec 13 Javascript
javascript 产生随机数的几种方法总结
Sep 26 Javascript
Vue 子组件与数据传递问题及注意事项
Jul 11 Javascript
TypeScript中使用getElementXXX()的示例代码
Sep 12 Javascript
vue学习笔记之过滤器的基本使用方法实例分析
Feb 01 Javascript
浅析 Vue 3.0 的组装式 API(一)
Aug 31 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
用mysql内存表来代替php session的类
2009/02/01 PHP
PHP读取mssql json数据中文乱码的解决办法
2016/04/11 PHP
PHP生成图像验证码的方法小结(2种方法)
2016/07/18 PHP
PHP中功能强大却很少使用的函数实例小结
2016/11/10 PHP
改进:论坛UBB代码自动插入方式
2006/12/22 Javascript
一个支付页面DEMO附截图
2014/07/22 Javascript
JavaScript中的ArrayBuffer详细介绍
2014/12/08 Javascript
JS显示下拉列表框内全部元素的方法
2015/03/31 Javascript
JavaScript Length 属性的总结
2015/11/02 Javascript
javascript中的3种继承实现方法
2016/01/27 Javascript
理解javascript封装
2016/02/23 Javascript
基于JS实现EOS隐藏错误提示层代码
2016/04/25 Javascript
AngularJs入门教程之环境搭建+创建应用示例
2016/11/01 Javascript
原生js实现弹出层效果
2017/01/20 Javascript
AngularJS页面传参的5种方式
2017/04/01 Javascript
ReactNative短信验证码倒计时控件的实现代码
2017/07/20 Javascript
es7学习教程之fetch解决异步嵌套问题的方法示例
2017/07/21 Javascript
基于Two.js实现星球环绕动画效果的示例
2017/11/06 Javascript
vue加载自定义的js文件方法
2018/03/13 Javascript
微信小程序实现订单倒计时
2020/11/01 Javascript
Vue实现仿iPhone悬浮球的示例代码
2020/03/13 Javascript
Element-ui el-tree新增和删除节点后如何刷新tree的实例
2020/08/31 Javascript
python字符串排序方法
2014/08/29 Python
Python中的True,False条件判断实例分析
2015/01/12 Python
Python的类实例属性访问规则探讨
2015/01/30 Python
Python计算三维矢量幅度的方法
2015/06/15 Python
tensorflow 获取模型所有参数总和数量的方法
2018/06/14 Python
pytorch permute维度转换方法
2018/12/14 Python
TripAdvisor印尼站:全球领先的旅游网站
2018/03/15 全球购物
数控专业大学生的自我鉴定
2013/11/13 职场文书
品质主管的岗位职责
2013/12/04 职场文书
生产车间主管岗位职责
2013/12/28 职场文书
护士个人自我鉴定
2014/03/24 职场文书
一年级评语大全
2014/04/23 职场文书
Linux安装Nginx步骤详解
2021/03/31 Servers
Oracle以逗号分隔的字符串拆分为多行数据实例详解
2021/07/16 Oracle