起因是这样的……
最近有一个需求:将使用 Openlist 存储的文档使用 Web 端预览……虽然理论上我的存储是 E5 ,可以使用微软od的预览器,但是这玩意有匿名速率限制且不方便接入。
当然,也有iframe预览器这种东西,然而当你打开一个130M的PPT,就会出现
(而且Google的预览器由于众所周知的原因并不能裸连)
那么我们就很有必要自己搭建一个预览器了……
啥是OnlyOfficen Document Server?
ONLYOFFICE Document Server is an online office suite comprising viewers and editors for texts, spreadsheets and presentations, fully compatible with Office Open XML formats: .docx, .xlsx, .pptx and enabling collaborative editing in real time.
简单来说,就是一个在Docker里面跑的、类似Microsoft Office Online的在线Office套件。
部署
官方文档:https://helpcenter.onlyoffice.com/docs/installation/docs-community-install-docker.aspx 首先,对于性能这块,官方是这么要求的:
- CPU: dual core 2 GHz or better
- RAM: 4 GB or more
- HDD: at least 40 GB of free space
- SWAP: at least 4 GB, but depends on the host OS. More is better
- OS: amd64 Linux distribution with kernel version 3.10 or later
但是其实实际拉下来只需要大约6GB的硬盘和400MiB的运行时内存。
先安个Docker。
应该都会那就跳过了然后拉一下镜像:
docker pull onlyoffice/documentserver:latest完整镜像5.7GB左右,请为服务器留足空间 然后,创建配置目录并启动容器:
mkdir ~/openoffice_config #这里的配置目录可以自己指定,但是记得在下面改sudo docker run -i -t -d -p 8080:80 --restart=always -v ~/onlyoffice_config:/etc/onlyoffice/documentserver -e JWT_SECRET=你的jwt密钥 onlyoffice/documentserver其中的8080是你想开放到宿主的端口,关于JWT_SECRET,这是为了防止他人使用,在调用是应该传入的访问密钥,可以自定义。但是在这个场景中,即使你有密钥,也会在前端明文,所以建议不配置:如果懒得配置密码,也可以将环境变量JWT_SECRET去掉,加上-e JWT_ENABLED=false,即:
mkdir ~/openoffice_configsudo docker run -i -t -d -p 8080:80 --restart=always -e -v ~/onlyoffice_config:/etc/onlyoffice/documentserver JWT_ENABLED=false onlyoffice/documentserver启动后访问对应的端口,你应该能看到:

#配置
修改最大下载大小
要把 OnlyOffice 作为预览器使用,我们还需要进行一些配置。默认情况下是不支持100MB以上的文件的,需要改配置文件,所以我们需要手动挂载并修改。 请确保你在上一步中创建的配置文件夹有效。
nano ~/onlyoffice_config/default.json #或你自己的配置目录定位到FileConverter中的converter块,修改maxDownloadBytes:
"converter": { "maxDownloadBytes": 10485760000, #原来是104857600.这个参数代表允许的最大文件大小,以字节计算,此处改为了10GB "downloadTimeout": { "connectionAndInactivity": "2m", "wholeCycle": "2m" },保存后重启容器:
docker restart $(docker ps -q --filter ancestor=onlyoffice/documentserver)搭建预览前端
要实现预览iframe我们还需要一个静态网页来调用onlyoffice的js。你可以使用各种Pages服务(如Github Pages,Cloudflare Pages,Netlify…)免费托管,这个对前端速度要求不大。可以参考如下的html,但是记得将<script>中的onlyoffice地址替换。
<!DOCTYPE html><html lang="zh-CN"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>OnlyOffice 预览器</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } html, body { width: 100%; height: 100%; overflow: hidden; background: #f5f5f5; } #placeholder { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; font-family: system-ui, -apple-system, sans-serif; color: #666; } .error { color: #d32f2f; background: #ffebee; padding: 16px 24px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } </style></head><body> <!-- OnlyOffice 编辑器将挂载到此容器 --> <div id="onlyoffice-container" style="width: 100%; height: 100%;"></div> <!-- 初始占位提示 --> <div id="placeholder">正在加载预览器...</div>
<script> (function() { // ==================== 配置 ==================== // 请替换为你的 OnlyOffice 文档服务地址 const DOCUMENT_SERVER_URL = 'http://example.com';
// ==================== 工具函数 ==================== // 从 URL 获取查询参数 function getQueryParam(name) { const params = new URLSearchParams(window.location.search); return params.get(name); }
// 从文件 URL 中提取文件名(作为备用) function getFileNameFromUrl(url) { try { const pathname = new URL(url, window.location.origin).pathname; const name = pathname.split('/').pop(); if (name && name.includes('.')) return name; return 'document'; } catch { return 'document'; } }
// 获取文件扩展名(不含点,小写) function getFileExtension(url) { const path = url.split('?')[0]; // 去除查询参数 const parts = path.split('.'); if (parts.length < 2) return ''; return parts.pop().toLowerCase(); }
// 根据扩展名判断 OnlyOffice 文档类型 function getDocumentType(extension) { const cellTypes = ['xls', 'xlsx', 'xlsm', 'xlsb', 'csv', 'ods', 'fods', 'ots']; const slideTypes = ['ppt', 'pptx', 'pptm', 'pps', 'ppsx', 'odp', 'fodp', 'otp'];
if (cellTypes.includes(extension)) return 'cell'; if (slideTypes.includes(extension)) return 'slide'; // 其余均视为文本文档(包括 .doc, .docx, .pdf, .txt, .rtf 等) return 'word'; }
// 隐藏占位元素 function hidePlaceholder() { const ph = document.getElementById('placeholder'); if (ph) ph.style.display = 'none'; }
// 显示错误信息 function showError(message) { const container = document.getElementById('onlyoffice-container'); const ph = document.getElementById('placeholder'); if (ph) ph.style.display = 'none'; container.innerHTML = `<div class="error">❌ ${message}</div>`; }
// ==================== 主逻辑 ==================== const fileUrl = getQueryParam('src');
// 如果没有提供 src 参数,显示错误 if (!fileUrl) { showError('缺少参数:请通过 ?src=文件URL 指定要预览的文件'); throw new Error('缺少 src 参数'); }
// 解码 URL(处理可能的编码) const decodedFileUrl = decodeURIComponent(fileUrl); const fileExtension = getFileExtension(decodedFileUrl); const fileName = getFileNameFromUrl(decodedFileUrl); const documentType = getDocumentType(fileExtension);
// 构建 OnlyOffice 配置(纯预览模式) const config = { document: { fileType: fileExtension, key: `${fileName}_${Date.now()}`, title: fileName, url: decodedFileUrl, }, documentType: documentType, editorConfig: { mode: 'view', // 仅预览,不可编辑 lang: 'zh-CN', }, height: '100%', width: '100%', // 可选:事件监听 events: { onAppReady: function() { hidePlaceholder(); console.log('OnlyOffice 编辑器已就绪'); }, onDocumentReady: function() { console.log('文档加载完成'); }, onError: function(error) { console.error('文档错误:', error); showError(`文档加载失败: ${error.data || '未知错误'}`); } } };
// 加载 OnlyOffice API 脚本并初始化 function loadOnlyOfficeAPI() { const script = document.createElement('script'); script.src = `${DOCUMENT_SERVER_URL}web-apps/apps/api/documents/api.js`; script.onload = function() { try { // 初始化编辑器 window.DocEditor = new DocsAPI.DocEditor('onlyoffice-container', config); } catch (e) { showError(`初始化失败: ${e.message}`); } }; script.onerror = function() { showError(`无法连接到 OnlyOffice 文档服务 (${DOCUMENT_SERVER_URL}),请检查服务地址或网络`); }; document.head.appendChild(script); }
// 开始加载 loadOnlyOfficeAPI(); })(); </script></body></html>预览前端html并不需要和后端在同一域名,但是推荐使用反向代理将其绑定到后端域名的/。
部署好之后,就可以通过预览器地址/?src=文件url这个iframe进行office文件的预览了。你也可以在OpenList的预览中iframe预览项目填写:
"doc,docx,xls,xlsx,ppt,pptx": { "OnlyOffice": "http(s)://你的预览器/?src=$e_url" },
对于 Onedrive 等下载链接不带后缀名的平台
例如Onedrive,在OpenList中得到的下载链接是同一download.aspx,无法通过后缀判断文件类型,这时就需要手动指定文件类型……具体方法可以咨询各大AI。
我一点都不想自建,只想白嫖?
好吧,既然你都看到这了。你也可以使用我搭建的服务,
https://previewfront.y-dev.tech/?src={YOUR_URL}会根据后缀名自动选择预览方式。