公司有一个小模块的业务需求,没有服务器需要实现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对象读取完成后再进行下一步操作。
此文仅记录一下自己每天杂乱无章的代码。