浅析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 相关文章推荐
js data日期初始化的5种方法
Dec 29 Javascript
一个奇葩的最短的 IE 版本判断JS脚本
May 28 Javascript
JS清除文本框内容离开在恢复及鼠标离开文本框时触发js的方法
Jan 12 Javascript
浅谈jquery的map()和each()方法
Jun 12 Javascript
JavaScript自定义文本框光标
Mar 05 Javascript
微信小程序 sha1 实现密码加密实例详解
Jul 06 Javascript
addeventlistener监听scroll跟touch(实例讲解)
Aug 04 Javascript
浅谈es6 javascript的map数据结构
Dec 14 Javascript
vue实现动态列表点击各行换色的方法
Sep 13 Javascript
VUE项目中加载已保存的笔记实例方法
Sep 14 Javascript
详解小程序如何改变onLoad的执行时机
Nov 01 Javascript
微信小程序实现简单文字跑马灯
May 26 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
超外差式晶体管收音机的组装与统调
2021/03/01 无线电
PHP递归复制、移动目录的自定义函数分享
2014/11/18 PHP
PHP利用正则表达式将相对路径转成绝对路径的方法示例
2017/02/28 PHP
PHP实现求两个字符串最长公共子串的方法示例
2017/11/17 PHP
XP折叠菜单&amp;仿QQ2006菜单
2006/12/16 Javascript
收集的网上用的ajax之chat.js文件
2007/04/08 Javascript
javascript CSS画图之基础篇
2009/07/29 Javascript
JavaScript高级程序设计 读书笔记之十一 内置对象Global
2012/03/07 Javascript
javascript学习笔记(十二) RegExp类型介绍
2012/06/20 Javascript
js控制不同的时间段显示不同的css样式的实例代码
2013/11/04 Javascript
jquery单行文字向上滚动效果的实现代码
2014/09/05 Javascript
JavaScript错误处理
2015/02/03 Javascript
JavaScript简单下拉菜单实例代码
2015/09/07 Javascript
跟我学习javascript的函数和函数表达式
2015/11/16 Javascript
JavaScript提升性能的常用技巧总结【经典】
2016/06/20 Javascript
jQuery实现鼠标经过像翻页和描点链接效果
2016/08/08 Javascript
JS实现PC手机端和嵌入式滑动拼图验证码三种效果
2017/02/15 Javascript
JavaScript实现三级联动效果
2017/07/15 Javascript
浅谈KOA2 Restful方式路由初探
2019/03/14 Javascript
使用Node.js实现base64和png文件相互转换的方法
2020/03/11 Javascript
js中!和!!的区别与用法
2020/05/09 Javascript
vue和小程序项目中使用iconfont的方法
2020/05/19 Javascript
vant自定义二级菜单操作
2020/11/02 Javascript
TensorFlow 合并/连接数组的方法
2018/07/27 Python
对python条件表达式的四种实现方法小结
2019/01/30 Python
Python元组常见操作示例
2019/02/19 Python
分享8点超级有用的Python编程建议(推荐)
2019/10/13 Python
python开发入门——set的使用
2020/09/03 Python
linux下进程间通信的方式
2014/12/23 面试题
PyQt QMainWindow的使用示例
2021/03/24 Python
网站开发实习生的自我评价
2013/12/11 职场文书
作文批改评语大全
2014/04/23 职场文书
2014年电厂个人工作总结
2014/11/27 职场文书
商务代表岗位职责
2015/02/15 职场文书
企业财务总监岗位职责
2015/04/03 职场文书
详解分布式系统中如何用python实现Paxos
2021/05/18 Python