news 2026/4/18 8:51:55

wangEditor pdf导入识别图表和文本高亮

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
wangEditor pdf导入识别图表和文本高亮

📝 Word一键转存CMS升级手记

🚀 项目背景

大家好,我是江西某高校计算机专业大三的"代码狂魔",正在给我的CMS新闻管理系统做一次"整容手术"——添加Word一键转存功能!每次看到编辑部的妹子们手动复制Word内容到后台,图片还要一张张上传,我就心疼(主要是心疼她们的加班费都拿去喝奶茶了)

🕵️ 技术调研

需求拆解

  1. 前端:在wangEditor工具栏添加导入按钮
  2. 功能:支持Word/Excel/PPT/PDF → 保留格式 → 图片自动上传
  3. 兼容:Win + Mac双平台
  4. 预算:99元(毕竟学生党,得留着钱买泡面)

方案探索

方案1: mammoth.js (纯前端方案)
// 测试代码片段importmammothfrom"mammoth";mammoth.extractRawText({arrayBuffer:fileArrayBuffer}).then(function(result){console.log(result.value);// 纯文本内容}).done();

✔️ 优点:免费、轻量
❌ 缺点:只能提取文本,丢失格式和图片

方案2: docx-parser (收费)

💰 价格:$199 → 超预算!PASS!

方案3: 阿里云OSS官方SDK + phpWord
// PHP后端处理逻辑usePhpOffice\PhpWord\IOFactory;$phpWord=IOFactory::load($tempFilePath);$writer=IOFactory::createWriter($phpWord,'HTML');$writer->save('converted.html');

✔️ 优点:格式保留较好
❌ 缺点:PPT/PDF支持有限

🔧 最终方案:wangEditor + paste-extension + 自定义处理

前端实现 (Vue2)

import E from 'wangeditor' import 'wangeditor/release/wangEditor.min.css' export default { data() { return { editor: null } }, mounted() { this.initEditor() }, methods: { initEditor() { this.editor = new E(this.$refs.editor) // 自定义菜单 this.editor.config.menus = [ 'head', 'bold', 'italic', 'underline', 'strikeThrough', 'foreColor', 'backColor', 'link', 'list', 'justify', 'quote', 'table', 'code', 'undo', 'redo', 'importWord' // 自定义按钮 ] // 注册自定义按钮 this.editor.config.customAlert = (s) => { console.log(s) } this.editor.config.customMenu = { importWord: { text: '导入Office', className: 'icon-import-word', callback: () => { document.getElementById('word-upload').click() } } } this.editor.create() }, async handleFileUpload(e) { const file = e.target.files[0] if (!file) return try { const formData = new FormData() formData.append('file', file) const res = await this.$http.post('/api/office/upload', formData, { headers: { 'Content-Type': 'multipart/form-data' } }) this.editor.txt.html(res.data.htmlContent) } catch (error) { console.error('文件上传失败:', error) } } } }

后端处理 (PHP)

ossClient=newOSS\OssClient(getenv('OSS_ACCESS_KEY_ID'),getenv('OSS_ACCESS_KEY_SECRET'),getenv('OSS_ENDPOINT'));$this->bucketName=getenv('OSS_BUCKET');}publicfunctionhandleUpload($file){$fileExt=strtolower(pathinfo($file['name'],PATHINFO_EXTENSION));$tempPath=$file['tmp_name'];switch($fileExt){case'doc':case'docx':return$this->processWord($tempPath);case'xls':case'xlsx':return$this->processExcel($tempPath);case'ppt':case'pptx':return$this->processPpt($tempPath);case'pdf':return$this->processPdf($tempPath);default:thrownewException("不支持的格式:$fileExt");}}privatefunctionprocessWord($filePath){$phpWord=\PhpOffice\PhpWord\IOFactory::load($filePath);$htmlWriter=new\PhpOffice\PhpWord\Writer\HTML($phpWord);// 处理图片$mediaElements=$phpWord->getMediaElements();foreach($mediaElementsas$element){$imagePath=$this->uploadImageToOSS($element['source'],$element['imageExtension']);// 替换HTML中的图片路径$htmlWriter->replaceImagePath($element['mediaIndex'],$imagePath);}$htmlContent=$htmlWriter->getContent();return['htmlContent'=>$htmlContent];}privatefunctionuploadImageToOSS($binaryData,$extension){$filename='uploads/'.uniqid().'.'.$extension;$this->ossClient->putObject($this->bucketName,$filename,$binaryData);return$this->ossClient->generatePresignedUrl($this->bucketName,$filename,3600);}// 其他格式处理方法类似...}?>

🎯 开发日志

Day1: 掉坑记

  1. 尝试用纯前端方案 → 图片处理被CORS拦路抢劫
  2. 试用phpWord → 发现PPT支持是个"半成品"
  3. 喝掉三罐红牛后决定:组合拳出击!

Day3: 突破性进展

  1. 发现阿里云OSS有文件处理服务(每月免费额度够用)
  2. 结合wangEditor的paste插件魔改成功
  3. 成功保留表格样式!(虽然颜色偶尔跑偏)

💡 技术要点总结

  1. 文件处理流程

    前端上传 → 后端识别格式 → 调用对应解析器 → 提取内容+图片 → 图片上传OSS → 生成HTML → 返回编辑器
  2. 成本控制技巧

    • 使用OSS免费额度
    • 用phpWord+phpExcel+phpPowerPoint组合替代商业库
    • 图片延迟加载减少流量消耗
  3. 兼容性hack

// 处理Mac系统差异constisMac=navigator.platform.toUpperCase().indexOf('MAC')>=0;if(isMac){// 调整某些API调用方式}

📚 推荐资源

  1. PHPOffice官方文档
  2. wangEditor扩展开发指南
  3. 阿里云OSS PHP SDK示例

🍻 结语

这个项目让我深刻体会到——“程序员的时间都去哪了?全花在找免费替代方案上了!” 欢迎加入QQ群223813913一起交流,群里不定期分享:

  • 熬夜不掉头发秘诀
  • 如何用学生认证白嫖各种云服务
  • 以及…我的完整项目代码!

(注:因篇幅限制,部分代码已简化,完整实现需要处理更多边界情况。需要详细代码可以进群@我)

复制插件文件


安装jquery

npm install jquery

导入组件

importEfrom'wangeditor'const{$,BtnMenu,DropListMenu,PanelMenu,DropList,Panel,Tooltip}=Eimport{WordPaster}from'../../static/WordPaster/js/w'import{zyCapture}from'../../static/zyCapture/z'import{zyOffice}from'../../static/zyOffice/js/o'

初始化组件

//zyCapture ButtonclasszyCaptureBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){window.zyCapture.setEditor(this.editor).Capture();}tryChangeActive(){this.active()}}//zyOffice ButtonclassimportWordBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){window.zyOffice.SetEditor(this.editor).api.openDoc();}tryChangeActive(){this.active()}}//zyOffice ButtonclassexportWordBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){window.zyOffice.SetEditor(this.editor).api.exportWord();}tryChangeActive(){this.active()}}//zyOffice ButtonclassimportPdfBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){window.zyOffice.SetEditor(this.editor).api.openPdf();}tryChangeActive(){this.active()}}//WordPaster ButtonclassWordPasterBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){WordPaster.getInstance().SetEditor(this.editor).Paste();}tryChangeActive(){this.active()}}//wordImport ButtonclassWordImportBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){WordPaster.getInstance().SetEditor(this.editor).importWord();}tryChangeActive(){this.active()}}//excelImport ButtonclassExcelImportBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){WordPaster.getInstance().SetEditor(this.editor).importExcel();}tryChangeActive(){this.active()}}//ppt paster ButtonclassPPTImportBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){WordPaster.getInstance().SetEditor(this.editor).importPPT();}tryChangeActive(){this.active()}}//pdf paster ButtonclassPDFImportBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){WordPaster.getInstance().SetEditor(this.editor);WordPaster.getInstance().ImportPDF();}tryChangeActive(){this.active()}}//importWordToImg ButtonclassImportWordToImgBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){WordPaster.getInstance().SetEditor(this.editor).importWordToImg();}tryChangeActive(){this.active()}}//network paster ButtonclassNetImportBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){WordPaster.getInstance().SetEditor(this.editor);WordPaster.getInstance().UploadNetImg();}tryChangeActive(){this.active()}}exportdefault{name:'HelloWorld',data(){return{msg:'Welcome to Your Vue.js App'}},mounted(){vareditor=newE('#editor');WordPaster.getInstance({//上传接口:http://www.ncmem.com/doc/view.aspx?id=d88b60a2b0204af1ba62fa66288203edPostUrl:"http://localhost:8891/upload.aspx",License2:"",//为图片地址增加域名:http://www.ncmem.com/doc/view.aspx?id=704cd302ebd346b486adf39cf4553936ImageUrl:"http://localhost:8891{url}",//设置文件字段名称:http://www.ncmem.com/doc/view.aspx?id=c3ad06c2ae31454cb418ceb2b8da7c45FileFieldName:"file",//提取图片地址:http://www.ncmem.com/doc/view.aspx?id=07e3f323d22d4571ad213441ab8530d1ImageMatch:''});zyCapture.getInstance({config:{PostUrl:"http://localhost:8891/upload.aspx",License2:'',FileFieldName:"file",Fields:{uname:"test"},ImageUrl:'http://localhost:8891{url}'}})// zyoffice,// 使用前请在服务端部署zyoffice,// http://www.ncmem.com/doc/view.aspx?id=82170058de824b5c86e2e666e5be319czyOffice.getInstance({word:'http://localhost:13710/zyoffice/word/convert',wordExport:'http://localhost:13710/zyoffice/word/export',pdf:'http://localhost:13710/zyoffice/pdf/upload'})// 注册菜单E.registerMenu("zyCaptureBtn",zyCaptureBtn)E.registerMenu("WordPasterBtn",WordPasterBtn)E.registerMenu("ImportWordToImgBtn",ImportWordToImgBtn)E.registerMenu("NetImportBtn",NetImportBtn)E.registerMenu("WordImportBtn",WordImportBtn)E.registerMenu("ExcelImportBtn",ExcelImportBtn)E.registerMenu("PPTImportBtn",PPTImportBtn)E.registerMenu("PDFImportBtn",PDFImportBtn)E.registerMenu("importWordBtn",importWordBtn)E.registerMenu("exportWordBtn",exportWordBtn)E.registerMenu("importPdfBtn",importPdfBtn)//挂载粘贴事件editor.txt.eventHooks.pasteEvents.length=0;editor.txt.eventHooks.pasteEvents.push(function(){WordPaster.getInstance().SetEditor(editor).Paste();e.preventDefault();});editor.create();varedt2=newE('#editor2');//挂载粘贴事件edt2.txt.eventHooks.pasteEvents.length=0;edt2.txt.eventHooks.pasteEvents.push(function(){WordPaster.getInstance().SetEditor(edt2).Paste();e.preventDefault();return;});edt2.create();}}h1,h2{font-weight:normal;}ul{list-style-type:none;padding:0;}li{display:inline-block;margin:010px;}a{color:#42b983;}

测试前请配置图片上传接口并测试成功
接口测试
接口返回JSON格式参考

为编辑器添加按钮

components:{Editor,Toolbar},data(){return{editor:null,html:'dd',toolbarConfig:{insertKeys:{index:0,keys:['zycapture','wordpaster','pptimport','pdfimport','netimg','importword','exportword','importpdf']}},editorConfig:{placeholder:''},mode:'default'// or 'simple'}},

整合效果

导入Word文档,支持doc,docx

导入Excel文档,支持xls,xlsx

粘贴Word

一键粘贴Word内容,自动上传Word中的图片,保留文字样式。

Word转图片

一键导入Word文件,并将Word文件转换成图片上传到服务器中。

导入PDF

一键导入PDF文件,并将PDF转换成图片上传到服务器中。

导入PPT

一键导入PPT文件,并将PPT转换成图片上传到服务器中。

上传网络图片

一键自动上传网络图片,自动下载远程服务器图片,自动上传远程服务器图片

下载示例

点击下载完整示例

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 19:04:35

GLM-4.6V-Flash-WEB模型在智慧办公场景下的典型应用

GLM-4.6V-Flash-WEB模型在智慧办公场景下的典型应用 在现代企业中&#xff0c;每天都有成千上万的截图、PPT、白板照片和扫描文档在员工之间流转。这些图像承载着关键信息——会议纪要、项目计划、财务数据、流程图示&#xff0c;但它们大多以“非结构化”的形式存在&#xff0…

作者头像 李华
网站建设 2026/4/17 17:05:00

网页大文件上传组件在SpringBoot中的性能优化方法

大文件传输系统解决方案 背景与需求分析 作为河南某上市集团的项目负责人&#xff0c;我们当前面临一个关键的技术挑战&#xff1a;需要为政府、央企等高端客户构建一个安全可靠的大文件传输系统。经过详细的需求调研&#xff0c;我整理了以下核心需求点&#xff1a; 超大文…

作者头像 李华
网站建设 2026/4/17 19:13:23

使用Flask包装GLM-4.6V-Flash-WEB模型提供HTTP服务

使用Flask包装GLM-4.6V-Flash-WEB模型提供HTTP服务 在当前AI应用快速落地的浪潮中&#xff0c;一个现实问题摆在许多开发者面前&#xff1a;手握强大的多模态模型&#xff0c;却困于“只能跑在笔记本上”的窘境。尤其是在图像理解、图文问答这类需要实时交互的场景下&#xff0…

作者头像 李华
网站建设 2026/4/18 1:41:05

GLM-4.6V-Flash-WEB模型在文物数字化保护中的辅助作用

GLM-4.6V-Flash-WEB模型在文物数字化保护中的辅助作用 在一座博物馆的数字化档案室里&#xff0c;工作人员正面对成千上万张尚未标注的文物图像——陶俑的衣饰细节、青铜器上的铭文、壁画中模糊的人物姿态。传统的人工判读方式不仅耗时费力&#xff0c;还高度依赖专家经验&…

作者头像 李华
网站建设 2026/4/18 4:31:25

GLM-4.6V-Flash-WEB模型能否替代传统OCR方案?对比实验

GLM-4.6V-Flash-WEB模型能否替代传统OCR方案&#xff1f;对比实验 在企业文档处理系统日益智能化的今天&#xff0c;一个现实问题正摆在开发者面前&#xff1a;我们是否还需要维护一套复杂的OCR流水线来提取文本&#xff0c;再叠加NLP模型进行理解&#xff1f;有没有可能用一个…

作者头像 李华