vue+express完成离线pdf文件预览

159 阅读2分钟

公司有一个小模块的业务需求,没有服务器需要实现pdf预览,我就借用了一下vue-office的功能,用nodejs编译了一个接口读取本地电脑指定的文件夹。

//读取存储pdf的文件夹
app.post('/pdf', async (req, res) => {
  try {
    const dirPath = 'c:/XX/XX'; // 文件夹路径
    const files = fs.readdirSync(dirPath); // 读取文件夹下的所有文件
    // 遍历文件列表并读取每个PDF文件的内容
    const pdfList = [];
    for (const file of files) {
      if (path.extname(file) === '.pdf') { // 如果文件是PDF文件
        const filePath = path.join(dirPath, file); // 获取文件完整路径
        const dataBuffer = fs.readFileSync(filePath); // 读取文件内容
        const pdfData = {
          fileName: file, // 添加文件名属性
          data: dataBuffer, // 添加文件内容属性
        };
        pdfList.push(pdfData); // 将打包好的对象添加到列表中
      }
    }
    res.send(pdfList); // 将列表作为响应发送回客户端
  } catch (err) {
    console.error(err);
    res.status(500).send('Server Error');
  }
});

读取文件时将文件流和文件名组成一个对象,传给前端一个ArrayBuffer类型的数组。

以下是前端的代码片段

 async getPdf() {
      try {
        const response = await axios.post("http://localhost:port/pdf", {}, {});
        response.data.forEach((item) => {
          this.dataList.push(item.data);
        });

        const blobList = this.dataList.map(
          (item) =>
            new Blob([new Uint8Array(item.data)], { type: "application/pdf" })
        );

        const arrayBufferList = await Promise.all(
          blobList.map((blob) => {
            return new Promise((resolve) => {
              const reader = new FileReader();
              reader.onload = () => resolve(reader.result);
              reader.readAsArrayBuffer(blob);
            });
          })
        );

        const pdfFiles = arrayBufferList.map((arrayBuffer, index) => ({
          name: response.data[index].fileName,
          src: URL.createObjectURL(
            new Blob([arrayBuffer], { type: "application/pdf" })
          ),
        }));
        this.pdfFiles = pdfFiles;
        this.currentPdfSrc = this.pdfFiles[0].src;
      } catch (err) {
        console.error(err);
      }
    },

我使用map()方法将每个ArrayBuffer类型数据转换为一个Blob对象,并将这些Blob对象存储在一个Array类型数组blobList中。然后使用Promise.all()方法和FileReader对象的readAsArrayBuffer()方法逐个读取blobList中的每个Blob对象,并将读取到的ArrayBuffer类型数据存储在arrayBufferList数组中。最后使用createObjectURL()方法将ArrayBuffer类型数据转换为一个URL,以便在页面中显示PDF文件。

这中间有一个小的问题点,就是开始是直接遍历加载我的blobList的,然后一直不显示我的pdf内容,最后查阅资料发现,由于FileReader对象的readAsArrayBuffer()方法是异步的,因此需要使用Promise对象进行等待,以便在每个Blob对象读取完成后再进行下一步操作。

此文仅记录一下自己每天杂乱无章的代码。