node实现word文档文件流的输出并在web端下载
2023-12-22 10:59:45
一、下载本地word文件
const express = require('express');
const fs = require('fs');
const cors = require('cors'); // 引入 cors 模块 实现跨域请求
const app = express();
const PORT = process.env.PORT || 3000;
// 使用 cors 中间件
app.use(cors());
app.get('/api/downloadLocalDocx', (req, res) => {
const filePath = './临时文档.doc'; // 替换为你的本地 Word 文档路径
// 使用 fs.createReadStream 读取本地文件流
const fileStream = fs.createReadStream(filePath);
//经测试,Content-Type为以前两个都能正常下载
// 设置响应头,指示返回的是 Word 文档
//res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
res.setHeader('Content-Type', 'application/octet-stream; charset=UTF-8');
// 设置响应头,指定下载时的文件名
res.setHeader('Content-Disposition', 'attachment; filename=local_document.docx');
// 将文件流传输给响应
fileStream.pipe(res);
});
app.listen(8000, () => {
console.log(`Server is running on port 8000`);
});
二、生成word文件
const express = require('express');
const officegen = require('officegen');
const fs = require('fs');
const cors = require('cors'); // 引入 cors 模块,实现跨域请求
const app = express();
const PORT = process.env.PORT || 3000;
// 使用 cors 中间件
app.use(cors());
app.get('/api/generateDocx', (req, res) => {
// 创建一个 Word 文档
const docx = officegen('docx');
const stream = fs.createWriteStream('generated_doc.docx');
// 添加内容到文档
docx.createP().addText('我是一个文本!', { font_face: 'Arial', font_size: 14 });
// 将生成的 Word 文档流写入文件
docx.generate(stream);
stream.on('finish', () => {
// 设置响应头,指示返回的是 Word 文档
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
// 下载文件
res.download('generated_doc.docx', 'generated_doc.docx', (err) => {
if (err) {
console.error('Error downloading file:', err);
}
// 删除生成的临时文件
fs.unlink('generated_doc.docx', (err) => {
if (err) {
console.error('Error deleting file:', err);
}
});
});
});
});
app.listen(8000, () => {
console.log(`Server is running on port 8000`);
});
三、web实现word文档的下载
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Generate and Download .docx</title>
</head>
<body>
<button id="downloadBtn">Download .docx</button>
<script>
document.getElementById('downloadBtn').addEventListener('click', () => {
fetch('http://localhost:8000/api/downloadLocalDocx') // 请替换为你的实际服务地址
.then(response => {
console.log('response: ', response);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
//return new Blob([response]);
return response.blob();
})
.then(blob => {
// 创建一个可下载链接
const url = window.URL.createObjectURL(blob);
// 创建一个<a>元素用于触发下载
const a = document.createElement('a');
a.href = url;
a.target = "_blank";
a.download = 'generated_doc.docx'; // 指定下载时的文件名
// 将<a>元素添加到DOM中
document.body.appendChild(a);
// 模拟用户点击下载链接
a.click();
// 完成后移除<a>元素和URL对象,释放资源
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
})
.catch(error => {
console.error('Error:', error);
});
});
</script>
</body>
</html>
四、在vue项目中,下载文件
exportExcel2(res, fileName) {
let blob = new Blob([res.data]);
const url = window.URL.createObjectURL(blob);
if (window.navigator.msSaveBlob) {
try {
window.navigator.msSaveBlob(blob, fileName);
} catch (e) {
console.log(e);
}
} else {
// 谷歌浏览器 创建a标签 添加download属性下载
let downloadElement = document.createElement("a");
downloadElement.href = url;
downloadElement.target = "_blank";
downloadElement.download = fileName;
document.body.appendChild(downloadElement);
downloadElement.click();
document.body.removeChild(downloadElement);
window.URL.revokeObjectURL(url);
}
},
showLoading(text = "请求中", target = "body"){
return this.$loading({
target: target,
lock: true,
text: text,
background: "rgba(255, 255, 255, 0.2)",
spinner: "el-icon-loading"
});
},
download(row) {
let loadingInstance = this.showLoading("正在导出", ".el-dialog__body");
downloadFile(row.id)
.then((res) => {
console.log('res====: ', res);
this.exportExcel2(res, row.name);
loadingInstance.close();
})
.catch((e) => {
loadingInstance.close();
});
},
但是下载的word文档是乱码,后经发现,是没有传入 responseType: “arraybuffer”,字段
export const downloadFile = (id) => {
return request({
url: `/api/XXX/report/download/${id}`,
method: 'get',
responseType: "arraybuffer",
})
}
在前端开发中,XMLHttpRequest对象被用于发送HTTP请求。responseType是XMLHttpRequest对象的一个属性,用于指定响应的数据类型。常见的值有:
“arraybuffer”: 以二进制数组的形式返回响应的数据。
“blob”:以二进制对象的形式返回响应的数据,通常用于处理图片等二进制文件。
“document”: 以Document对象的形式返回响应的数据。
“json”: 以JSON对象的形式返回响应的数据。
“text”: 以字符串的形式返回响应的数据。
文章来源:https://blog.csdn.net/weixin_40466351/article/details/135124201
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!