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
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。