nodejs實(shí)現(xiàn)生成文件并在前端下載
nodejs生成文件并在前端下載
最近遇到一個(gè)小需求,前端要下載一個(gè)json文件,內(nèi)容是對(duì)應(yīng)數(shù)據(jù)的json對(duì)象。
看網(wǎng)上寫的都太復(fù)雜了,只是下載一個(gè)小文件,只需要用到res.end()就夠了。
前端
在a標(biāo)簽上加上download屬性就可以點(diǎn)擊下載文件了,download可以賦值,值為下載之后的文件名。也可以留空,用原有的文件名。
<a href="/xxxxx" rel="external nofollow" download>導(dǎo)出</a>
后端
響應(yīng)頭需要設(shè)置這兩個(gè)屬性“Content-type”,“Content-Disposition”
然后用res.end()寫入數(shù)據(jù),數(shù)據(jù)一定是字符串形式。
filename是文件名
var jsonstr_data = JSON.stringify(obj);
res.set({
"Content-type":"application/octet-stream",
"Content-Disposition":"attachment;filename="+encodeURI(filename)
});
res.end(jsonstr_data);
nodejs下載文件問(wèn)題
第一種方式:使用原生的http模塊
我們僅需要用到fs和http兩個(gè)node.js的原生模塊,不需要安裝第三方模塊,就可以實(shí)現(xiàn)文件的下載。代碼如下:
var fs = require('fs');
var http = require("http");
var server = http.createServer();
server.on("request", function (request, response) {
// 獲取請(qǐng)求URL
var url = request.url;
// 如果是下載文件的URL,則判斷進(jìn)行處理
if (url === '/download/hello.txt') {
// 提取文件名hello.txt
var name = url.substring(url.lastIndexOf('/'));
// 創(chuàng)建可讀流,讀取當(dāng)前項(xiàng)目目錄下的hello.txt文件
var rs = fs.createReadStream(__dirname + "/" + name);
// 設(shè)置響應(yīng)請(qǐng)求頭,200表示成功的狀態(tài)碼,headers表示設(shè)置的請(qǐng)求頭
response.writeHead(200, {
'Content-Type': 'application/force-download',
'Content-Disposition': 'attachment; filename=' + name
});
// 將可讀流傳給響應(yīng)對(duì)象response
rs.pipe(response);
}
});
server.listen(8888, function () {
console.log("服務(wù)器啟動(dòng)成功,可以通過(guò) http://127.0.0.1:8888 來(lái)進(jìn)行訪問(wèn)");
});
然后可以通過(guò)http://127.0.0.1:8888/download/hello.txt下載文件。

第二種方式:使用Express+Axios下載文件
前端通過(guò)axios發(fā)送GET或者POST請(qǐng)求來(lái)進(jìn)行文件的下載,關(guān)鍵是對(duì)響應(yīng)回來(lái)的文件數(shù)據(jù)進(jìn)行處理。
index.html:前端頁(yè)面,通過(guò)點(diǎn)擊按鈕來(lái)進(jìn)行下載文件,而請(qǐng)求是通過(guò)axios來(lái)發(fā)送的。
<!DOCTYPE html>
<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) {
// 將響應(yīng)回來(lái)的數(shù)據(jù)下載為文件,固定代碼
// 將響應(yīng)數(shù)據(jù)處理為Blob類型
var blob = new Blob([response.data]);
// 創(chuàng)建一個(gè)URL對(duì)象
var url = window.URL.createObjectURL(blob);
// 創(chuàng)建一個(gè)a標(biāo)簽
var a = document.createElement("a");
a.href = url;
a.download = "hello.txt";// 這里指定下載文件的文件名
a.click();
// 釋放之前創(chuàng)建的URL對(duì)象
window.URL.revokeObjectURL(url);
}).catch(function (reason) {
console.log(reason)
})
}
</script>
</html>
index.js:使用express來(lái)渲染index.html頁(yè)面,并且來(lái)處理下載請(qǐng)求。
var fs = require('fs');
var express = require('express');
var app = express();
// 渲染index.html,跟下載邏輯無(wú)關(guān)
app.get('/index.html', function (request, response) {
fs.readFile('index.html', function (err, data) {
if (!err) {
response.end(data);
}
});
});
// 處理下載文件的請(qǐng)求
app.post('/file/download', function (request, response) {
var name = "hello.txt";// 待下載的文件名
var path = __dirname + "/" + name;// 待下載文件的路徑,指定為當(dāng)前項(xiàng)目目錄下的hello.txt文件
var f = fs.createReadStream(path);
response.writeHead(200, {
'Content-Type': 'application/force-download',
'Content-Disposition': 'attachment; filename=' + name
});
f.pipe(response);
});
// 監(jiān)聽(tīng)端口,相當(dāng)于原來(lái)的server.listen()
app.listen(8888, function () {
console.log("app is running at port 8888.");
});

又可以通過(guò)response.set()方法來(lái)設(shè)置響應(yīng)頭:
response.set({
'Content-Type': 'application/octet-stream',// 告訴瀏覽器這是一個(gè)二進(jìn)制文件
'Content-Disposition': 'attachment; filename=' + name// 告訴瀏覽器這是一個(gè)需要下載的文件
});
總結(jié)
下載文件其實(shí)很簡(jiǎn)單,在哪種語(yǔ)言里都是這樣:
- 第一步,設(shè)置響應(yīng)頭。
- 第二步,返回?cái)?shù)據(jù)流。
設(shè)置響應(yīng)頭
下載文件需要設(shè)置的響應(yīng)頭是Content-Type和Content-Disposition,響應(yīng)頭與編程語(yǔ)言無(wú)關(guān),是通用的。
'Content-Type': 'application/octet-stream'表示這是一個(gè)二進(jìn)制文件。'Content-Disposition': 'attachment;filename=hello.txt'表示這是一個(gè)需要下載的附件,并且告訴瀏覽器默認(rèn)文件名。
返回?cái)?shù)據(jù)流
讀取要下載的文件,以二進(jìn)制流的形式響應(yīng)給客戶端。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- nginx利用referer指令實(shí)現(xiàn)防盜鏈配置
- Nginx防盜鏈的配置方法
- Nginx服務(wù)器下防盜鏈的方法介紹
- Nginx圖片防盜鏈配置實(shí)例
- 配置Nginx的防盜鏈的操作方法
- Springboot四種事件監(jiān)聽(tīng)的實(shí)現(xiàn)方式詳解
- node+axios實(shí)現(xiàn)下載外網(wǎng)文件到本地
- nodejs連接ftp上傳下載實(shí)現(xiàn)方法詳解【附:踩坑記錄】
- Node.js實(shí)現(xiàn)下載文件的兩種實(shí)用方式
- Node.js實(shí)現(xiàn)批量下載圖片簡(jiǎn)單操作示例
- node.js突破nginx防盜鏈機(jī)制,下載圖片案例分析
相關(guān)文章
express項(xiàng)目文件目錄說(shuō)明以及功能描述詳解
這篇文章主要給大家介紹了關(guān)于express項(xiàng)目文件目錄說(shuō)明以及功能描述的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
手把手教你VSCode配置JavaScript基于Node.js的調(diào)試環(huán)境
最近在補(bǔ)數(shù)據(jù)結(jié)構(gòu),在用VScode調(diào)試js代碼文件結(jié)果怎么都不行,這篇文章主要給大家介紹了關(guān)于VSCode配置JavaScript基于Node.js的調(diào)試環(huán)境的相關(guān)資料,需要的朋友可以參考下2022-12-12
node.js中的fs.readFileSync方法使用說(shuō)明
這篇文章主要介紹了node.js中的fs.readFileSync方法使用說(shuō)明,本文介紹了fs.readFileSync的方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12
使用Node.js實(shí)現(xiàn)Clean?Architecture方法示例詳解
這篇文章主要為大家介紹了使用Node.js實(shí)現(xiàn)Clean?Architecture方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
Node.js的MongoDB驅(qū)動(dòng)Mongoose基本使用教程
這篇文章主要介紹了Node.js的MongoDB驅(qū)動(dòng)Mongoose的基本使用教程,前端js+后端Node.js+數(shù)據(jù)庫(kù)MongoDB是當(dāng)下流行的JavaScript全棧開(kāi)發(fā)方案,需要的朋友可以參考下2016-03-03
基于docker搭建node環(huán)境開(kāi)發(fā)服務(wù)器全過(guò)程
這篇文章主要給大家介紹了關(guān)于如何基于docker搭建node環(huán)境開(kāi)發(fā)服務(wù)器的相關(guān)資料,本文將采用docker技術(shù)部署一個(gè)簡(jiǎn)單的nodejs應(yīng)用,文中通過(guò)圖文以及代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11
nestjs中異常過(guò)濾器Exceptionfilter的具體使用
這篇文章主要介紹了nestjs中異常過(guò)濾器Exceptionfilter的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02
如何在NestJS中添加對(duì)Shopify的WebHook驗(yàn)證詳解
這篇文章主要為大家介紹了如何在NestJS中添加對(duì)Shopify的WebHook驗(yàn)證詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08

