目录
- 第一种方式:使用原生的http模块
- 第二种方式:使用Express+Axios下载文件
- 总结
- 设置响应头
- 返回数据流
第一种方式:使用原生的http模块
我们仅需要用到fs
和http
两个node.js的原生模块,不需要安装第三方模块,就可以实现文件的下载。代码如下:
var fs = require('fs'); | |
var http = require("http"); | |
var server = http.createServer(); | |
server.on("request", function (request, response) { | |
// 获取请求URL | |
var url = request.url; | |
// 如果是下载文件的URL,则判断进行处理 | |
if (url === '/download/hello.txt') { | |
// 提取文件名hello.txt | |
var name = url.substring(url.lastIndexOf('/')); | |
// 创建可读流,读取当前项目目录下的hello.txt文件 | |
var rs = fs.createReadStream(__dirname + "/" + name); | |
// 设置响应请求头,200表示成功的状态码,headers表示设置的请求头 | |
response.writeHead(200, { | |
'Content-Type': 'application/force-download', | |
'Content-Disposition': 'attachment; filename=' + name | |
}); | |
// 将可读流传给响应对象response | |
rs.pipe(response); | |
} | |
}); | |
server.listen(8888, function () { | |
console.log("服务器启动成功,可以通过 http://127.0.0.1:8888 来进行访问"); | |
}); |
然后可以通过http://127.0.0.1:8888/download/hello.txt下载文件。
第二种方式:使用Express+Axios下载文件
前端通过axios发送GET或者POST请求来进行文件的下载,关键是对响应回来的文件数据进行处理。
index.html
:前端页面,通过点击按钮来进行下载文件,而请求是通过axios来发送的。
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<!-- 引入axios.js --> | |
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> | |
</head> | |
<body> | |
<button onclick="downloadFile()">下载</button> | |
</body> | |
<script> | |
function downloadFile() { | |
axios({ | |
url: '/file/download', | |
method: 'POST', | |
responseType: 'blob' | |
}).then(function (response) { | |
// 将响应回来的数据下载为文件,固定代码 | |
// 将响应数据处理为Blob类型 | |
var blob = new Blob([response.data]); | |
// 创建一个URL对象 | |
var url = window.URL.createObjectURL(blob); | |
// 创建一个a标签 | |
var a = document.createElement("a"); | |
a.href = url; | |
a.download = "hello.txt";// 这里指定下载文件的文件名 | |
a.click(); | |
// 释放之前创建的URL对象 | |
window.URL.revokeObjectURL(url); | |
}).catch(function (reason) { | |
console.log(reason) | |
}) | |
} | |
</script> | |
</html> |
index.js
:使用express来渲染index.html页面,并且来处理下载请求。
var fs = require('fs'); | |
var express = require('express'); | |
var app = express(); | |
// 渲染index.html,跟下载逻辑无关 | |
app.get('/index.html', function (request, response) { | |
fs.readFile('index.html', function (err, data) { | |
if (!err) { | |
response.end(data); | |
} | |
}); | |
}); | |
// 处理下载文件的请求 | |
app.post('/file/download', function (request, response) { | |
var name = "hello.txt";// 待下载的文件名 | |
var path = __dirname + "/" + name;// 待下载文件的路径,指定为当前项目目录下的hello.txt文件 | |
var f = fs.createReadStream(path); | |
response.writeHead(200, { | |
'Content-Type': 'application/force-download', | |
'Content-Disposition': 'attachment; filename=' + name | |
}); | |
f.pipe(response); | |
}); | |
// 监听端口,相当于原来的server.listen() | |
app.listen(8888, function () { | |
console.log("app is running at port 8888."); | |
}); |
又可以通过response.set()
方法来设置响应头:
response.set({ | |
'Content-Type': 'application/octet-stream',// 告诉浏览器这是一个二进制文件 | |
'Content-Disposition': 'attachment; filename=' + name// 告诉浏览器这是一个需要下载的文件 | |
}); |
总结
下载文件其实很简单,在哪种语言里都是这样:
第一步,设置响应头。第二步,返回数据流。
设置响应头
下载文件需要设置的响应头是Content-Type
和Content-Disposition
,响应头与编程语言无关,是通用的。
'Content-Type': 'application/octet-stream'
表示这是一个二进制文件。
'Content-Disposition': 'attachment;filename=hello.txt'
表示这是一个需要下载的附件,并且告诉浏览器默认文件名。
返回数据流
读取要下载的文件,以二进制流的形式响应给客户端。