如何在HTML中创建适配Firefox的PDF侧边预览页面?
本地PDF浏览器查看工具解决方案
问题说明
你需要在Firefox中实现一个左右分栏的PDF查看页面:左侧显示指定文件夹里的PDF文件列表,点击后右侧用类似原生预览的方式展示PDF。你自己编写的代码无法生效,以下是问题分析和修正方案。
原代码的问题
- 浏览器安全限制:直接用
fetch访问file://协议的本地目录,Firefox出于安全策略会阻止这类操作——前端JS不允许直接读取本地文件系统的目录结构。 - 语法错误:
<style>标签内多余的css字符串、<script>标签内多余的javascript字符串,会导致样式和脚本无法正常解析。 - 结构错误:脚本放在
<ul>标签内部,不符合HTML结构规范,可能引发元素获取异常。
解决方案
基于浏览器安全限制,提供两种可行实现方式:
方式一:本地静态服务器(推荐,适合固定文件夹)
浏览器允许从本地服务器读取目录内容,用Python快速搭建静态服务器:
- 打开命令行,进入PDF文件夹的父目录(比如
C:/Users/F170593/Desktop/) - 运行命令:
# Python 3版本 python -m http.server 8000 - 用Firefox访问
http://localhost:8000,即可通过服务器访问PDF文件夹。
修正后的代码(把/pdfs/替换为你的PDF文件夹相对服务器根目录的路径):
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>PDF查看器</title> <style> body, html { height: 100%; margin: 0; font-family: Arial, sans-serif; } .container { display: flex; height: 100%; } .lista { width: 30%; overflow-y: auto; border-right: 1px solid #ccc; padding: 10px; } .visualizador { width: 70%; padding: 10px; } li { cursor: pointer; padding: 8px; margin: 4px 0; border-radius: 4px; } li:hover { background-color: #f0f0f0; } </style> </head> <body> <div class="container"> <div class="lista"> <ul id="listaArquivos"></ul> </div> <div class="visualizador"> <iframe id="pdfViewer" width="100%" height="100%" src="" frameborder="0"></iframe> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const listaArquivos = document.getElementById('listaArquivos'); const pdfViewer = document.getElementById('pdfViewer'); // 服务器上PDF文件夹的路径,比如桌面的pdfs文件夹就写'/pdfs/' const diretorio = "/pdfs/"; fetch(diretorio) .then(response => response.text()) .then(text => { const parser = new DOMParser(); const xmlDoc = parser.parseFromString(text, "text/html"); const items = xmlDoc.querySelectorAll('a'); items.forEach(item => { const nomeArquivo = item.textContent; if (nomeArquivo.endsWith('.pdf')) { const li = document.createElement('li'); li.textContent = nomeArquivo; li.addEventListener('click', function() { pdfViewer.src = diretorio + nomeArquivo; }); listaArquivos.appendChild(li); } }); }) .catch(err => { listaArquivos.innerHTML = '<li>无法加载文件列表,请检查服务器路径</li>'; console.error(err); }); }); </script> </body> </html>
方式二:File System Access API(无需服务器,手动选文件夹)
Firefox 111及以上版本支持该API,允许用户手动选择本地文件夹后读取其中的PDF:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>PDF查看器</title> <style> body, html { height: 100%; margin: 0; font-family: Arial, sans-serif; } .container { display: flex; height: 100%; } .lista { width: 30%; overflow-y: auto; border-right: 1px solid #ccc; padding: 10px; } .visualizador { width: 70%; padding: 10px; } li { cursor: pointer; padding: 8px; margin: 4px 0; border-radius: 4px; } li:hover { background-color: #f0f0f0; } .select-btn { padding: 8px 16px; margin-bottom: 10px; cursor: pointer; background-color: #007bff; color: white; border: none; border-radius: 4px; } .select-btn:hover { background-color: #0056b3; } </style> </head> <body> <div class="container"> <div class="lista"> <button class="select-btn" id="selectFolder">选择PDF文件夹</button> <ul id="listaArquivos"></ul> </div> <div class="visualizador"> <iframe id="pdfViewer" width="100%" height="100%" src="" frameborder="0"></iframe> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const selectFolderBtn = document.getElementById('selectFolder'); const listaArquivos = document.getElementById('listaArquivos'); const pdfViewer = document.getElementById('pdfViewer'); selectFolderBtn.addEventListener('click', async () => { try { const handle = await window.showDirectoryPicker(); listaArquivos.innerHTML = ''; // 遍历文件夹内的PDF文件 for await (const entry of handle.values()) { if (entry.kind === 'file' && entry.name.endsWith('.pdf')) { const file = await entry.getFile(); const url = URL.createObjectURL(file); const li = document.createElement('li'); li.textContent = entry.name; li.addEventListener('click', () => { pdfViewer.src = url; }); listaArquivos.appendChild(li); } } } catch (err) { listaArquivos.innerHTML = '<li>选择文件夹失败或取消选择</li>'; console.error(err); } }); }); </script> </body> </html>
内容的提问来源于stack exchange,提问作者Jeff_f_f
相关产品推荐
相关产品推荐

