首页 / 资讯中心 / 文章详情

eWebEditor 11.0:老后台Word导入与IIS部署实践

eWebEditor 11.0:老后台Word导入与IIS部署实践 ★ FEATURED ARTICLE
简介eWebEditor11.0中文商业版是一套面向网站开发者与内容管理人员的所见即所得在线编辑器支持在网页中直接编辑图文混排的文章、新闻、通告与讨论贴并内置 Word 导入等常用能力适合需要快速搭建后台编辑模块的项目场景。压缩包共 718 个文件约 30.09MB主要由 gif、css、jpg 等界面与样式资源htm、aspx 页面及少量 js、dll、exe 组件构成兼顾前端皮肤、服务端示例与运行依赖目录结构较完整。已有 872 人学习或下载便于读者参考商业版的组织方式与功能配置。通过包内示例页、配置文件和上传、分页、登录等模块可了解编辑器在真实站点中的接入思路、界面定制与常见功能调试方法。1. eWebEditor 11.0 中文商业版老后台里最省事的 Word 导入方案维护一套跑了多年的内容后台编辑提的需求往往不是“换框架”而是“从 Word 里复制过来的表格别再散架”。eWebEditor 11.0 中文商业版正是为这类场景准备的一套 ASP 时代的富文本编辑器带完整工具栏、多套皮肤以及内置的 Word 导入与粘贴过滤。它并不新按钮的审美停在 Office 2003 那一代但只要站点还跑在 IIS 上它仍是改造成本最低的一档整目录拷进去配置在后台点几下对外只暴露取值和回填两个方法。适合手上有一堆老页面、又不想重写编辑器的同学也适合给内网系统补一个能吞 Word 排版录入框的运维。2. 目录结构与运行环境把编辑器在 IIS 上跑通的最小闭环拿到压缩包先别急着解压到桌面双击看效果。这套东西是服务端脚本 静态资源的组合脱离 IIS 直接开 HTML 文件只会看到一个空白 iframe然后误判成“包是坏的”。整章按“先认清目录、再配环境、最后验证”三步走每一步都能独立判断成败。2.1 先认清三个区服务端脚本、皮肤包、上传落地区解开之后的根目录大致分三块职责完全不同目录内容能不能动asp/或asp.net/、php/、jsp/等并列目录服务端脚本、配置读写、上传处理、取值接口只改配置不改核心逻辑style/皮肤工具栏按钮图、CSS、按钮分组定义可增删皮肤但目录名要和后台配置一致uploadfile/图片、附件落地目录必须给写权限且必须禁脚本执行admin/或后台入口样式管理、上传参数、工具栏裁剪上线前必须改口令、限制访问来源最容易翻车的一步是“只拷了asp/目录”。编辑器主体是一个 iframe里面加载的按钮图、CSS 全在style/下脚本在、皮肤不在页面会渲染出一排没有图标的灰按钮F12 里一串 404。血泪经验整目录原样拷贝不要挑挑拣拣。另外多语言版本的目录是并列的ASP 站点只需要asp/和style/其余语言目录可以删掉——留着不但占空间某些上传入口还能被直接访问到属于自己给自己开后门。2.2 IIS 与应用池ASP、32 位、父路径三个开关老 ASP 程序在新版 Windows Server 上跑不起来九成是这三个开关没开。用管理员权限的 CMD 一次性配完# 1) 确认 ASP 可选功能装了没没装直接装 dism /online /get-featureinfo /featurename:IIS-ASP dism /online /enable-feature /featurename:IIS-ASP /all # 2) 独立应用池托管管道用经典模式开启 32 位 # 老组件、mdb 驱动基本都是 32 位的64 位池子里调不起来 %windir%\system32\inetsrv\appcmd add apppool /name:eWebEditorPool /managedRuntimeVersion: /enable32BitAppOnWin64:true %windir%\system32\inetsrv\appcmd set apppool eWebEditorPool /managedPipelineMode:Classic # 3) 老代码大量用 !--#include file../inc/config.asp--父路径必须放开 %windir%\system32\inetsrv\appcmd set config Default Web Site/eweb /section:asp /enableParentPaths:true /commit:apphost # 4) 联调期打开脚本错误回显方便定位上线前务必关回去 %windir%\system32\inetsrv\appcmd set config Default Web Site/eweb /section:asp /scriptErrorSentToBrowser:true /commit:apphost参数逐条解释一下。/enable32BitAppOnWin64:true是决定生死的一行32 位组件在 64 位工作进程里注册表根本读不到表现是“上传按钮点了没反应、也没有报错”典型的黑匣子现象。/managedPipelineMode:Classic是因为老 ASP 依赖 ISAPI 扩展的通配映射集成模式下*.asp的请求可能直接被静态处理接管。enableParentPaths关着的时候#include用相对父级路径会直接抛 500错误信息还特别含糊只告诉你包含文件失败。scriptErrorSentToBrowser我一般只在联调那两天开它会把源码行号和变量值一起吐到浏览器上上线忘了关就是免费的信息泄露。这个后悔药必须提前吃。2.3 用一张最小验证页确认工具栏能出来环境配完不要直接往业务页面里嵌。先丢一个纯静态的验证页到站点根目录只有它能正常显示工具栏才说明脚本、皮肤、路径三条链路都通了!-- /eweb/test.html 仅用于联调上线前删掉 -- !DOCTYPE html html headmeta charsetutf-8titleeditor probe/title/head body iframe ided src/eweb/ewebeditor/asp/ewebeditor.asp?idcontent1stylestandard frameborder0 scrollingno stylewidth:100%;height:420px;border:1px solid #ccc/iframe script // 必须等 iframe 内部脚本初始化完再探测onload 之前读到的都是 null document.getElementById(ed).onload function () { var w this.contentWindow; console.log(eWebEditor:, typeof w.eWebEditor); // 编辑器对象挂在 window 上 console.log(editdoc :, typeof w.editdoc); // 老版本直接暴露编辑区 console.log(keys :, w.eWebEditor ? Object.keys(w.eWebEditor).slice(0, 12) : []); }; /script /body /htmlsrc里两个参数是关键idcontent1是编辑器实例标识后面取值回填、多编辑器共存都靠它区分stylestandard指向style/下的皮肤目录名写错了不会报错只会加载一套默认样式或者干脆空白属于典型的静默失败。第三个参数通常还有宽高但我更建议用外层 iframe 的 CSS 控制避免两边打架。打印出来的keys是下一步的线索——不同小版本暴露的方法名有出入有的叫getHTML有的叫getValue照着实际输出对号入座比翻文档快。如果eWebEditor是undefined而editdoc有值说明这版没挂全局对象后面走兜底路径。提示验证页的路径一定要用站点绝对路径/eweb/...。部署在虚拟目录下时编辑器内部的相对路径计算经常出错用绝对路径能避开一大半“资源 404 但文件明明在”的玄学问题。3. 嵌入与取值三处接口对位决定编辑器能不能用跑通之后就是接进业务表单。这一步的坑不在于代码复杂而在于“编辑器不是原生表单控件”这个事实——它不会跟着form一起提交取了值不塞进隐藏域后端收到的永远是空字符串。3.1 iframe 嵌入与两个必填参数嵌入方式就是上一章的 iframe区别在于业务页面里要给它一个稳定的容器处理尺寸自适应div classeditor-wrap styleposition:relative iframe ided nameed src/eweb/ewebeditor/asp/ewebeditor.asp?idcontent1stylestandard frameborder0 scrollingno stylewidth:100%;height:420px;border:1px solid #d0d0d0/iframe /div script // 窗口变化时同步高度避免小屏下编辑区被压成一条缝 function fitEditor() { var wrap document.querySelector(.editor-wrap); var h Math.max(320, window.innerHeight - wrap.getBoundingClientRect().top - 120); document.getElementById(ed).style.height h px; } window.addEventListener(resize, fitEditor); fitEditor(); /scriptMath.max(320, ...)里的 320 是最小高度低于这个值工具栏会换行按钮挤成一坨。- 120是给底部保存按钮留的空间按自己页面调整。这个函数看着琐碎但在 1366×768 的办公机上不做自适应编辑区会被压到只剩两行编辑第一件事就是找你投诉。3.2 取值与回填一层封装挡住版本差异业务页面里不要直接写contentWindow.eWebEditor.getHTML()一旦换版本或者某个页面嵌了两个编辑器改起来是灾难。我一般封一层// 统一封装屏蔽不同小版本的方法名差异同时支持多实例 var Editor { frame: function (id) { return document.getElementById(id || ed); }, getHTML: function (id) { var w this.frame(id).contentWindow; if (w.eWebEditor typeof w.eWebEditor.getHTML function) return w.eWebEditor.getHTML(); if (w.eWebEditor typeof w.eWebEditor.getValue function) return w.eWebEditor.getValue(); if (w.editdoc w.editdoc.body) return w.editdoc.body.innerHTML; // 兜底路径 return ; }, setHTML: function (html, id) { var w this.frame(id).contentWindow; var v html || ; if (w.eWebEditor typeof w.eWebEditor.setHTML function) { w.eWebEditor.setHTML(v); return true; } if (w.eWebEditor typeof w.eWebEditor.setValue function) { w.eWebEditor.setValue(v); return true; } if (w.editdoc w.editdoc.body) { w.editdoc.body.innerHTML v; return true; } return false; }, getText: function (id) { var w this.frame(id).contentWindow; if (w.eWebEditor typeof w.eWebEditor.getText function) return w.eWebEditor.getText(); return this.getHTML(id).replace(/[^]/g, ).replace(/nbsp;/g, ).trim(); } };三层判断的顺序是有讲究的先试标准方法再试旧版方法名最后才动editdoc.body.innerHTML。最后这条兜底会绕过编辑器内部的一些格式化钩子比如自动补p、清理空标签所以只在前两条都取不到时才用。getText单独拎出来是为了做非空校验——直接拿 HTML 判断空用户敲几个空格加一个br就能骗过去。配套的提交逻辑form idf methodpost action/eweb/save.asp onsubmitreturn syncEditor(); input typehidden namecontent1 idcontent1 button typesubmit保存/button /form script function syncEditor() { var text Editor.getText(); if (text.length 0) { alert(正文不能为空); return false; } if (text.length 20000) { alert(正文超出长度限制请拆分或精简); return false; } // 关键一步编辑器内容不会跟着表单走必须手动塞进隐藏域 document.getElementById(content1).value Editor.getHTML(); return true; } /scriptnamecontent1和 iframe 的idcontent1参数保持一致只是习惯两者并不自动关联真正起作用的是那行赋值。长度校验放在前端只是提升体验服务端save.asp里必须再判一次前端拦不住的。3.3 工具栏裁剪与样式配置改后台别改源码默认工具栏塞得满满当当字体、字号、颜色、表格、特殊符号、源码切换全在。业务上往往只需要一半多出来的按钮就是误操作来源。正确做法是进后台的样式管理选一个皮肤勾选保留的按钮组保存后刷新即可。配置位置作用调整建议样式管理 → 工具栏按钮组控制显示哪些按钮只留加粗、字号、列表、表格、图片、链接、清除格式样式管理 → 编辑区宽高初始尺寸交给外层 CSS 控制这里填自适应占位值上传设置 → 允许的扩展名白名单图片只留 jpg/png/gif/webp附件单独走上传设置 → 单文件大小上限限制和 IIS 请求上限对齐不要一边 2M 一边 50M过滤设置 → Word 粘贴过滤清洗强度见下一章普通和严格两档要按业务选直接改style/下的 JS 数组是能生效但后台再用图形界面点一次保存改动就被覆盖回去了排查时能让人怀疑人生。配置统一走后台源码目录只读。注意删掉“源码”按钮能挡掉一批误操作但挡不住直接构造 POST。服务端save.asp入库前一定要对on*事件属性和script做一次清洗别把编辑器当信任边界。4. Word 导入链路的两个入口粘贴过滤与文档解析的参数取舍Word 导入是这套编辑器最有价值的部分也是坑最多的部分。它实际有两条完全不同的链路一条走剪贴板粘贴一条走整份文档上传。两条链路的失败原因、能保留的格式范围、性能开销都不一样混着讲永远理不清。4.1 粘贴链路剪贴板 HTML → 过滤器 → 入库用户在 Word 里选中一段带合并单元格、带底纹的表格CtrlC切到编辑器 CtrlV。浏览器从剪贴板拿到的是text/html格式内容长这样!--StartFragment--包裹的片段标记一大堆mso-前缀的内联样式比如mso-table-lspace、mso-para-margino:p这类 Office 命名空间标签图片位置是v:shapev:imagedata srcfile:///C:/Users/...指向本地临时文件最后一条是硬伤file:///路径在服务端和别的机器上都不存在粘贴进来必然是一个裂图。所以Word 粘贴天然只能保排版不能保图片图片必须让用户单独走上传按钮或者走第二条链路。这点在需求评审时就要跟业务说清楚不然上线后第一个反馈就是“图都没了”。过滤强度一般有三档对应后台的过滤设置档位保留内容代价不过滤原样保留所有mso-样式单篇内容轻松上百 KB页面加载慢样式还会污染整站普通过滤保留字体、字号、颜色、对齐、表格结构仍残留部分mso-声明需要服务端兜底清严格过滤只留基础标签表格列宽、行高、底纹基本丢失复杂排版会被压平我一般的选法是普通过滤 服务端二次清洗。严格过滤看着干净但业务方拿一份带三线表的报表进来出来变成没有边框的纯文本返工成本比清洗脏标签高得多。4.2 清洗规则服务端兜底才靠得住前端过滤依赖编辑器内部脚本跑完任何一个 JS 异常、网络抖动、用户提前点保存都可能让脏 HTML 直接落库。所以入库前必须再过一遍。ASP 环境里用 VBScript 正则最省事 save.asp 入库前的兜底清洗不依赖前端是否过滤成功 Function CleanWordHTML(s) Dim re Set re New RegExp re.IgnoreCase True re.Global True 1) Word 的条件注释里面的内容浏览器根本不渲染纯占体积 re.Pattern !--\[if[\s\S]*?!\[endif\]-- s re.Replace(s, ) 2) Office 命名空间标签脱离 Word 后没有意义 re.Pattern /?o:p[^]* s re.Replace(s, ) re.Pattern /?v:[a-zA-Z][^]* s re.Replace(s, ) 3) mso- 开头的样式声明保留 font-size / text-align 等通用属性 re.Pattern mso-[a-z-]\s*:\s*[^;];? s re.Replace(s, ) 4) 清空后残留的 style / class删掉能显著减小体积 re.Pattern \s(style|class)\s*\s*\s* s re.Replace(s, ) CleanWordHTML s End Function逐条说参数。第一条的正则用了非贪婪[\s\S]*?因为条件注释可以跨行用.不加SingleLine会匹配不到!\[endif\]--里的方括号必须转义。第三条是整段清洗的核心mso-声明动辄二三十条删完通常能砍掉 60% 以上的体积但要注意它只匹配“属性名以 mso- 开头”的font-size、color这些通用声明会原样保留排版不会塌。清洗完建议再跑一次体积判断超过 200KB 的直接拒绝入库并提示用户精简这比事后清库省事得多。4.3 文档导入链路参数、组件依赖和一条更稳的旁路第二条链路是“导入 Word 文档”用户可以选一个.doc文件服务端解析后回填到编辑区。老版本通常依赖服务器上装了 Office 组件通过 COM 调用转换。这条路的问题很集中服务器必须装对应版本的 Office且是 32 位组件和 2.2 节的应用池位数要对上COM 调用是单线程的并发三个用户同时导入就可能排队超时进程残留是常态任务管理器里一堆WINWORD.EXE得配计划任务定期清只在 IE 内核下工作现代浏览器直接不生效所以现在的常见做法是绕开 COM.docx本质是 zip图片全在word/media/下用命令行解出来再按顺序回填src稳定且无进程残留# 把 docx 解包图片按体积从大到小排第一张通常是封面或主图 mkdir -p /tmp/docx unzip -o upload.docx -d /tmp/docx ls -S /tmp/docx/word/media | head -n 10 # 文档正文在 word/document.xml图片引用关系看 word/_rels/document.xml.rels grep -o r:embed[^]* /tmp/docx/word/document.xml | head这里的关键是document.xml.rels里的关系映射r:embedrId5对应的真实文件名要在这张表里查不能按image1.png、image2.png的顺序硬猜Word 生成的序号经常是乱序的。老式的.doc二进制格式没有这层结构只能靠 COM 或者第三方转换服务这时候老老实实降级成“提示用户另存为 docx”——比在服务器上养一个 Office 进程池划算。提示如果业务坚持要支持.doc把转换做成独立的小服务超时 30 秒强制杀进程主站只负责上传和取结果。放在同一个进程里做一次卡死会拖垮整个编辑器。5. 避坑与排查五类现场每条都对应一个具体报错下面这五条是按“上线后最常被叫去救火”的频率排的每条都能对应到一个具体的控制台报错或者现象照着对号入座即可。5.1 工具栏渲染出来但按钮是灰块控制台一串 404现象iframe 能加载编辑区能输入文字但工具栏一排空白方块F12 网络面板里style/standard/下的图片全是 404。原因皮肤目录没拷全或者站点部署在虚拟目录下之后编辑器内部用相对路径拼出来的图片地址层级算错了。还有一种情况是把style/拷到了asp/里面路径多了一层。解决先确认style/standard/下的图片文件齐全再看 iframe 请求的实际 URL 和文件真实位置差几层。差一层的把嵌入代码的src改成站点绝对路径/eweb/ewebeditor/asp/ewebeditor.asp多数情况能直接解决。5.2 正文一长就 500短内容正常现象粘贴一份两页的 Word 内容点保存直接 500短文本没问题。IIS 日志里是POST大小超限。原因两处限制互相独立都要调。requestFiltering的maxAllowedContentLength默认约 30MB够用但 ASP 的limits.maxRequestEntityAllowed默认只有 200KBWord 粘一段带样式的表格轻松超过。解决# 两处一起调只调一处等于没调 %windir%\system32\inetsrv\appcmd set config Default Web Site/eweb ^ /section:system.webServer/security/requestFiltering ^ /requestLimits.maxAllowedContentLength:20971520 /commit:apphost %windir%\system32\inetsrv\appcmd set config Default Web Site/eweb ^ /section:asp /limits.maxRequestEntityAllowed:20971520 /commit:apphost两个值都是字节数20MB 对纯文本内容已经很宽松。调完记得iisreset配置缓存有时候不刷新。5.3 中文全变问号英文正常现象编辑区里输入的汉字保存后变成???或者显示成一串乱码。原因三处编码不一致。.asp文件被存成了 UTF-8 带 BOMBOM 会在% Language %之前输出三个字节导致响应头已经发出、Response.CharSet设不上去页面meta charset和数据库字段排序规则又是另一套。解决把服务端.asp文件统一另存为 UTF-8 无 BOM 或 ANSI在文件头部显式设Response.CharSet utf-8和Session.CodePage 65001并确认meta charsetutf-8与之匹配。三处对齐之后乱码基本消失只对齐一两处会变成“有时正常有时乱”的玄学。5.4 上传按钮点了没反应或者提示组件未注册现象点插入图片弹窗打开但选文件后一直转圈或者直接弹一个“组件无法创建对象”的提示。原因应用池没开 32 位32 位上传组件在 64 位进程里注册表读不到或者uploadfile/目录没给IIS_IUSRS写权限。解决回 2.2 节确认enable32BitAppOnWin64:true已生效再给上传目录加写权限icacls C:\inetpub\eweb\ewebeditor\uploadfile /grant IIS_IUSRS:(OI)(CI)(M) /T(OI)(CI)是让权限继承到子目录和文件(M)是修改权限比直接给完全控制稳妥。只给读权限的表现是“上传成功但图片裂”容易误判成路径问题。5.5 在 Edge 里按钮全灰换台机器又好了现象同样地址老机器上正常新装的机器上工具栏按钮点不动或者粘贴没反应。原因这一代编辑器大量依赖 IE 的document.execCommand和剪贴板访问权限在 Chromium 内核下这些接口行为完全不同。能不能用取决于浏览器是否以 IE 模式渲染。解决给站点配企业模式站点列表强制该域名用 IE 模式打开同时确认页面头部没有强制X-UA-Compatible到边缘模式。这条无解的部分要认新版浏览器上只能做到“能用”做不到“好用”长期方案还是把它当成过渡组件新模块不要继续往上堆。6. 加固与回归上传白名单、目录权限和上线前的六项自检这套东西年代久上传入口是重点加固对象。最低限度做三件事扩展名白名单在服务端判、落地文件重命名为时间戳加随机串、上传目录禁止任何脚本处理器执行。!-- web.configuploadfile 目录只允许静态文件访问任何脚本都不执行 -- configuration location pathewebeditor/uploadfile system.webServer handlers clear / add nameStaticOnly path* verbGET,HEAD modulesStaticFileModule resourceTypeEither requireAccessRead / /handlers /system.webServer /location /configurationclear /是这行的重点——不先把继承下来的处理器清空父级的*.asp映射照样生效等于白配。只留GET,HEADverb里不给POST双重保险。上线前我会固定跑一遍这张表六项全绿才敢交给业务检查项判定标准编辑器加载工具栏图标齐全控制台无 404取值回填保存后重新打开格式和内容一致Word 粘贴表格结构保留无mso-残留无file:///图片长内容粘贴 3 页 Word 内容能正常保存无 500上传图片能传能显示改成.asp后缀被拒目录上传目录直接访问脚本返回 404 或下载不执行最后一项最容易被忽略也最值得反复验。以前图省事只在后台白名单里加了一行结果服务端判的还是客户端提交的Content-Type改个请求头就绕过去了。从那以后我每次接这类老编辑器都会先手动构造一个改名请求打一遍上传入口确认它在服务端被拒再往下做别的。这个习惯救过至少两次。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站