news 2026/6/10 13:00:14

教育平台如何用wangEditor插件实现PPT动画转存?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
教育平台如何用wangEditor插件实现PPT动画转存?

银行后台管理系统新闻模块 PDF 导入功能开发纪实

我是苏州一家银行的开发人员,近期我们项目组接到了一个新需求:要在后台管理系统的新闻模块中增加 PDF 导入功能,导入后需将 PDF 转换成图片并上传到服务器。我们项目前端用的是 vue2 - cli 框架,编辑器是 wangEditor4,后端采用 SpringBoot 框架,数据库为 Oracle。为了找到合适的解决方案,我开启了一段充满挑战的开发之旅。

开源项目查找:大海捞针

广泛撒网

我首先在 GitHub、Gitee 等开源代码托管平台上进行搜索,输入关键词如“PDF 转图片”“PDF 导入前端”“Vue PDF 处理”等,期望能找到可以直接集成到我们项目中的开源项目。浏览了大量项目后,发现很多项目存在各种问题。

有些项目虽然能实现 PDF 转图片,但依赖的库版本与我们现有项目不兼容。比如有一个项目使用了较新版本的 PDF 解析库,而我们的项目环境无法支持该版本,升级环境又可能引发其他依赖冲突,风险太大。还有些项目功能不够完善,只能实现简单的 PDF 转图片,对于复杂的 PDF 文档,如包含大量图表、特殊字体的文档,转换效果很差,图片会出现模糊、乱码等问题。

精准筛选

在排除了大量不合适的项目后,我将搜索范围缩小到与 Vue 和 SpringBoot 结合较好的项目。找到几个看似有潜力的项目,其中一个项目提供了前端 PDF 预览和转换图片的接口,后端也有相应的处理逻辑。但深入测试后发现,它在处理大文件 PDF 时性能极差,转换时间长达数分钟,而且经常出现内存溢出错误,这显然无法满足银行系统对稳定性和高效性的要求。

另一个项目虽然转换速度较快,但缺乏对 PDF 文档权限的控制。银行系统中的新闻模块可能涉及一些敏感信息,如果导入的 PDF 文档有权限限制,该项目无法正确处理,可能会导致信息泄露风险。经过反复权衡,我决定放弃寻找现成的开源项目,采用自主研发的方式来实现这个功能。

开发过程:披荆斩棘

前端开发:搭建桥梁

  1. 引入 PDF 解析库
    在前端,我选择了 pdf.js 这个广泛使用的开源库来解析 PDF 文档。首先在 vue2 - cli 项目中通过 npm 安装 pdf.js:
npminstallpdfjs - dist

然后在需要使用的地方引入并初始化:

import*aspdfjsLibfrom'pdfjs - dist';// 设置 pdf.js 工作线程的路径(根据实际情况调整)pdfjsLib.GlobalWorkerOptions.workerSrc='//cdnjs.cloudflare.com/ajax/libs/pdf.js/2.10.377/pdf.worker.min.js';
  1. 实现 PDF 预览和转换图片
    创建一个 Vue 组件来处理 PDF 的导入和转换。在组件中,添加文件选择按钮,当用户选择 PDF 文件后,使用 pdf.js 读取文件内容,并将每一页转换为图片。
export default { data() { return { pdfPages: [] }; }, methods: { handlePdfUpload(event) { const file = event.target.files[0]; if (file) { const fileReader = new FileReader(); fileReader.onload = (e) => { const typedArray = new Uint8Array(e.target.result); this.renderPdfPages(typedArray); }; fileReader.readAsArrayBuffer(file); } }, async renderPdfPages(pdfData) { const loadingTask = pdfjsLib.getDocument({ data: pdfData }); const pdf = await loadingTask.promise; this.pdfPages = []; for (let i = 1; i <= pdf.numPages; i++) { const page = await pdf.getPage(i); const viewport = page.getViewport({ scale: 1.0 }); const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; const renderContext = { canvasContext: context, viewport: viewport }; await page.render(renderContext).promise; this.pdfPages.push(canvas.toDataURL('image/png')); } // 调用后端接口上传图片 this.uploadImagesToServer(); }, uploadImagesToServer() { // 这里实现与后端的交互,上传图片数据 // 后续会详细介绍 } } };
  1. 与 wangEditor4 集成
    将转换后的图片插入到 wangEditor4 编辑器中。在上传图片到服务器成功后,获取图片的 URL,然后使用 wangEditor4 的 API 将图片插入到编辑器内容中。
// 假设已经获取到图片 URL 数组 imageUrlsinsertImagesToEditor(imageUrls){consteditor=this.$refs.editor.editor;// 获取 wangEditor4 实例imageUrls.forEach(url=>{editor.cmd.do('insertHTML',``);});}

后端开发:稳固后盾

  1. 搭建 SpringBoot 项目结构
    使用 Spring Initializr 创建一个新的 SpringBoot 项目,添加必要的依赖,如 Spring Web、Oracle JDBC 驱动等。配置好数据库连接信息,确保项目能够正常访问 Oracle 数据库。
org.springframework.boot spring - boot - starter - web com.oracle.database.jdbc ojdbc8 21.5.0.0
  1. 实现图片上传接口
    创建一个 SpringBoot 控制器来处理前端上传的图片数据。在接口中,接收前端发送的图片数据,将其保存到服务器指定目录,并将图片信息存储到 Oracle 数据库中。
importorg.springframework.beans.factory.annotation.Value;importorg.springframework.web.bind.annotation.*;importorg.springframework.web.multipart.MultipartFile;importjava.io.File;importjava.io.IOException;importjava.util.UUID;@RestController@RequestMapping("/api/pdf - images")publicclassPdfImageUploadController{@Value("${image.upload.dir}")privateStringimageUploadDir;@PostMapping("/upload")publicStringuploadImage(@RequestParam("file")MultipartFilefile){try{StringoriginalFilename=file.getOriginalFilename();StringfileExtension=originalFilename.substring(originalFilename.lastIndexOf("."));StringnewFilename=UUID.randomUUID().toString()+fileExtension;Filedest=newFile(imageUploadDir+File.separator+newFilename);file.transferTo(dest);// 这里可以将图片信息存储到 Oracle 数据库,示例省略数据库操作代码return"http://your - server - domain/images/"+newFilename;}catch(IOExceptione){e.printStackTrace();return"上传失败";}}}
  1. 配置服务器存储路径
    在 SpringBoot 的配置文件中(如 application.properties 或 application.yml),配置图片上传的服务器目录:
# application.properties 示例 image.upload.dir=/path/to/your/server/image/upload/directory

前后端联调:紧密协作

在前后端分别完成开发后,进行联调测试。前端调用后端图片上传接口,将转换后的图片数据发送到后端。后端接收数据并处理后,返回图片的访问 URL 给前端。前端根据返回的 URL 将图片插入到 wangEditor4 编辑器中。

在联调过程中,遇到了跨域问题。由于前端和后端运行在不同的端口上,浏览器出于安全考虑阻止了跨域请求。通过在 SpringBoot 后端添加跨域配置解决了这个问题:

importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.CorsRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;@ConfigurationpublicclassCorsConfigimplementsWebMvcConfigurer{@OverridepublicvoidaddCorsMappings(CorsRegistryregistry){registry.addMapping("/**").allowedOrigins("*").allowedMethods("GET","POST","PUT","DELETE","OPTIONS").allowedHeaders("*");}}

测试与优化:精益求精

功能测试

对 PDF 导入功能进行全面测试,包括不同大小、不同格式复杂度的 PDF 文档。测试导入过程中是否出现错误,图片转换是否准确,上传到服务器是否成功,以及图片在编辑器中的显示是否正常。

性能测试

模拟多用户同时导入 PDF 文档的场景,测试系统的性能和稳定性。发现当大量用户同时上传大文件 PDF 时,服务器资源占用过高,导致响应时间变长。通过优化图片压缩算法、增加服务器带宽和调整线程池配置等方式,提高了系统的性能和并发处理能力。

安全测试

对系统进行安全测试,检查是否存在信息泄露、文件上传漏洞等安全问题。确保上传的 PDF 文档和图片都经过安全检查,防止恶意文件上传攻击。

经过一段时间的努力,PDF 导入功能终于成功上线并稳定运行。在这个过程中,我深刻体会到了自主研发的挑战和成就感。虽然遇到了很多困难,但通过不断学习和尝试,最终找到了合适的解决方案,满足了银行项目的需求。未来,我将继续关注技术发展,不断优化系统性能,为银行的信息化建设贡献自己的力量。

复制插件文件


安装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/6/10 14:06:27

垃圾定时投放监管系统设计

垃圾定时投放监管系统设计 第一章 绪论 随着垃圾分类政策的推进&#xff0c;垃圾定时定点投放成为规范分类行为的关键措施&#xff0c;但当前存在投放时间无序、违规投放难追溯、监管人力成本高等问题&#xff0c;影响分类成效。垃圾定时投放监管系统通过技术手段实现投放时间…

作者头像 李华
网站建设 2026/6/10 11:35:37

短剧春节档开打:漫剧成平台新争夺战场!

在过去几年中&#xff0c;春节档一直是短剧行业实现破圈突围的关键跳板。过去的短剧依靠“电子年货”属性&#xff0c;成功吸引了数亿用户&#xff0c;内容从“娱乐快餐”升级为“正餐硬菜”&#xff0c;实现了与电影、长剧三足鼎立的局面。然而&#xff0c;随着短剧市场格局的…

作者头像 李华
网站建设 2026/6/10 11:41:50

Windows文件过滤驱动MiniFilter导致的死锁问题分析

摘要Windows文件过滤驱动&#xff08;File Filter Driver&#xff09;是操作系统中用于拦截和处理文件I/O请求的重要组件。MiniFilter框架作为现代文件过滤驱动的标准实现方式&#xff0c;为开发者提供了便捷的驱动开发接口。然而&#xff0c;由于其独特的工作机制和复杂的内核…

作者头像 李华
网站建设 2026/6/10 11:35:47

‌危机管理测试:从灾害事件学故障切换

故障切换不是技术动作&#xff0c;而是系统韧性的心跳‌ 在软件测试领域&#xff0c;‌“故障切换”‌&#xff08;failover&#xff09;早已超越了“主备切换”的技术实现&#xff0c;演变为一场‌系统级的危机管理演练‌。真正的测试者&#xff0c;不再满足于“验证服务是否…

作者头像 李华
网站建设 2026/6/10 8:55:35

定稿前必看!AI论文平台 千笔 VS Checkjie,专为本科生打造!

随着人工智能技术的迅猛迭代与普及&#xff0c;AI辅助写作工具已逐步渗透到高校学术写作场景中&#xff0c;成为本科生完成毕业论文不可或缺的辅助手段。越来越多面临毕业论文压力的学生&#xff0c;开始依赖各类AI工具简化写作流程、提升创作效率。但与此同时&#xff0c;市场…

作者头像 李华
网站建设 2026/6/10 8:52:13

Agent、Workflow、RAG_还是_Skill?

本文通过AI内容产品实战案例&#xff0c;剖析了AI系统架构设计的核心误区与演进路径。提出真正的AI产品护城河在于承载真实世界复杂性&#xff0c;而非单纯依赖模型能力。详细阐述了ModelRAGSkillWorkflow架构设计的实践方法论&#xff0c;强调构建最小完备内核&#xff0c;用慢…

作者头像 李华