中国铁路XX局集团公司 - CMS系统新闻模块Word导入功能升级项目实施记录
一、项目背景与需求确认
1. 集团需求分析
- 核心功能:
- 在CMS后台新闻编辑模块中新增Word文档一键导入功能,支持
.docx格式。 - 自动提取Word中的文本、图片、表格、标题样式、字体颜色、超链接等元素,并1:1还原至富文本编辑器。
- 图片需自动上传至集团指定服务器(支持华为云OBS信创版),并替换Word中的原始引用路径。
- 在CMS后台新闻编辑模块中新增Word文档一键导入功能,支持
- 信创环境要求:
- 操作系统:Windows 10/11、macOS 12+、统信UOS 1050+、中标麒麟V7/V10、银河麒麟V10 SP1、龙芯3A5000(LoongArch架构)。
- 数据库:达梦DM8、人大金仓KingbaseES V8/V9。
- 开发框架:前端Vue2-cli + 百度UEditor 1.4.3.3(信创适配版),后端SpringBoot 2.7.x。
- 服务要求:
- 提供7×24小时在线技术支持,故障响应时间≤15分钟,支持远程协助与紧急补丁热部署。
2. 项目目标
- 实现高保真Word内容解析,兼容铁路行业常用文档模板(如红头文件、列车时刻表等)。
- 通过等保2.0三级测评,确保数据传输加密(SM4算法)与存储安全。
二、技术选型与产品评估
1. 候选方案分析
| 方案 | 可行性评估 |
|---|---|
| Apache POI + docx4j | 优势:开源免费,支持复杂样式解析; |
| 风险:docx4j在龙芯平台性能较差,表格合并单元格处理不稳定。 | |
| 商业SDK(如Spire.Doc) | 优势:高保真转换,支持信创认证; |
| 风险:授权费用高(约¥12,000/年/核心)。 | |
| 开源组件(如WordPaster) | 优势:高保真转换,支持信创认证;整合简单,集成简单,使用简单,完全开放产品源代码(点击免费下载源码),满足政企100%自主安全可控需求,国内唯一提供7*24小时在线技术支持:(QQ群:223813913) |
| 风险:需要终端安装控件。 | |
| 开源组合方案 | 决策方案: |
- 文本/表格解析:Apache POI 5.2.3(XWPF模块)。
- 图片提取:自定义ZIP解压流处理(
.docx本质为ZIP包)。 - 样式还原:基于UEditor插件扩展,映射Word样式至CSS。 |
关键决策点:
- 放弃docx4j,改用POI+自定义渲染引擎,解决龙芯平台兼容性问题。
- 图片处理采用前端预解析+后端异步上传模式,减少用户等待时间。
2. 技术栈确认
- 前端:
- Vue2-cli + UEditor 1.4.3.3(信创版,移除XSS过滤限制)。
- 集成
mammoth.js(轻量级Word解析库)实现客户端预览。 - 使用
webpack-plugin-compress优化打包体积,兼容统信UOS浏览器。
- 后端:
- SpringBoot 2.7.12 + Apache POI 5.2.3(处理
.docx文件流)。 - 异步任务:Spring Task + RabbitMQ(信创版)实现图片上传队列。
- 图片压缩:使用
Thumbnailator库生成缩略图(宽≤800px)。
- SpringBoot 2.7.12 + Apache POI 5.2.3(处理
- 信创适配:
- 龙芯平台:替换
org.apache.poi.xwpf.usermodel中依赖x86指令的代码段。 - 数据库驱动:达梦JDBC 8.1.1.193(支持JDBC 4.2规范)。
- 龙芯平台:替换
三、开发实施过程
1. 前端开发(Vue2 + UEditor)
-
步骤1:扩展UEditor文件上传组件。
// src/plugins/ueditor/ueditor.config.js UE.registerEditor('news-editor', { toolbars: [['source', 'undo', 'redo', 'wordimage', 'insertimage']], wordImageUpload: { url: '/api/upload/word-image', fieldName: 'file', accept: 'image/*' }, // 自定义Word粘贴处理 pasteFilter: function(html) { // 拦截Word粘贴的垃圾标签(如) return html.replace(/|\sclass="MsoNormal"|style="mso-*"/g, ''); } }); // 监听Word导入按钮点击事件 document.getElementById('import-word-btn').onclick = function() { const input = document.createElement('input'); input.type = 'file'; input.accept = '.docx'; input.onchange = async (e) => { const file = e.target.files[0]; const loading = layer.load(2, { shade: [0.5, '#000'] }); // 显示加载层 try { // 前端预解析Word内容(使用mammoth.js) const result = await mammoth.extractRawText({ arrayBuffer: await file.arrayBuffer() }); const html = result.value .replace(/\n/g, '') // 简单换行处理(实际需更复杂逻辑) .replace(/\[图片(\d+)\]/g, (match, p1) => { // 占位符,后端替换为真实图片URL return ``; }); // 插入到UEditor UE.getEditor('news-editor').setContent(html); // 上传Word文件至后端解析图片 const formData = new FormData(); formData.append('file', file); const res = await axios.post('/api/parse/word', formData); // 替换图片占位符 const editor = UE.getEditor('news-editor'); res.data.imageUrls.forEach(img => { editor.setContent( editor.getContent().replace( `data-word-img-id="${img.originalId}"`, `src="${img.url}"` ) ); }); } finally { layer.close(loading); } }; input.click(); }; -
步骤2:样式映射表配置。
// 定义Word样式到CSS的映射关系 const styleMap = [ { wordStyle: 'Heading1', css: 'font-size: 22px; font-weight: bold; color: #1f497d;' }, { wordStyle: 'TableGrid', css: 'border: 1px solid #000;' }, // ...其他样式规则 ];
2. 后端开发(SpringBoot)
-
步骤1:Word文件解析服务。
// src/main/java/com/railway/service/WordParserService.java @Service public class WordParserService { @Autowired private ObsClient obsClient; // 华为云OBS客户端 public Map parseWordImages(MultipartFile file) throws IOException { Map imageMap = new HashMap<>(); // {图片ID: OBS URL} try (ZipInputStream zip = new ZipInputStream(file.getInputStream())) { ZipEntry entry; while ((entry = zip.getNextEntry()) != null) { if (entry.getName().startsWith("word/media/") && entry.getName().endsWith(".png")) { // 提取图片并上传至OBS ByteArrayOutputStream baos = new ByteArrayOutputStream(); IOUtils.copy(zip, baos); String imageId = UUID.randomUUID().toString(); String url = obsClient.putObject( "railway-cms-media", "word-images/" + imageId + ".png", new ByteArrayInputStream(baos.toByteArray()) ); imageMap.put(entry.getName().split("/")[2].replace(".png", ""), url); } } } return imageMap; } // 处理Word文档整体导入 public String importWordToHtml(MultipartFile file) throws Exception { // 1. 解析图片 Map imageUrls = parseWordImages(file); // 2. 使用POI解析文本内容(简化版示例) XWPFDocument document = new XWPFDocument(file.getInputStream()); StringBuilder html = new StringBuilder(""); for (XWPFParagraph para : document.getParagraphs()) { String style = para.getStyle(); html.append(String.format("%s", getStyleCss(style), // 根据styleMap转换CSS para.getText())); } html.append(""); // 3. 替换图片占位符 imageUrls.forEach((id, url) -> { html = new StringBuilder(html.toString().replace("[" + id + "]", url)); }); return html.toString(); } private String getStyleCss(String wordStyle) { // 实际需从数据库或配置文件中查询映射关系 return "font-family: SimSun; font-size: 12pt;"; } } -
步骤2:异步图片上传优化。
# application-prod.yml spring: rabbitmq: host: 10.0.0.50 username: admin password: ${RABBITMQ_PASS} virtual-host: /cms task: execution: thread-name-prefix: "word-parse-task-" pool: core-size: 8 max-size: 16
3. 信创环境兼容性处理
- 操作系统适配:
- 龙芯平台:修改POI源码,替换
sun.misc.Unsafe相关操作为标准Java API。 - 银河麒麟:调整JVM参数
-Djava.awt.headless=true避免图形界面依赖冲突。
- 龙芯平台:修改POI源码,替换
- 数据库优化:
- 达梦数据库:为图片URL字段添加
全文索引,支持快速检索。 - 人大金仓:配置
work_mem = 64MB以提升大文本处理性能。
- 达梦数据库:为图片URL字段添加
四、测试与验证
1. 功能测试
- Word测试用例:
- 含50页复杂文档(嵌套表格、跨页标题、页眉页脚)的导入验证。
- 测试红头文件模板的样式保留(如宋体+加粗+红色标题)。
- 验证超链接与书签的转换准确性。
2. 信创兼容性测试
- 统信UOS + 龙芯3A5000:
- 使用
strace -f跟踪系统调用,确保无x86指令集依赖。
- 使用
- 中标麒麟V10:
- 验证
glibc版本兼容性(需≥2.17)。
- 验证
3. 性能测试
- 压力测试:
- 模拟10个并发导入任务,CPU占用率≤65%,内存泄漏≤50MB/小时。
- 长耗时测试:
- 200MB Word文件导入耗时≤90秒(含图片上传)。
五、技术支持与运维方案
-
7×24小时服务保障:
- 部署Zabbix + Prometheus监控系统,实时告警任务队列积压。
- 提供信创专家坐席,支持远程桌面(向日葵信创版)与电话指导。
-
知识转移:
- 交付《Word样式映射配置手册》《龙芯平台调优指南》。
- 录制UEditor插件开发教程视频,覆盖样式还原逻辑。
六、项目交付成果
-
功能模块:
- 新闻编辑器新增“Word导入”按钮,支持拖拽上传。
- 图片自动压缩(质量85%),支持WebP格式以节省带宽。
-
文档清单:
- 《信创环境部署指南》《API接口规范》《性能测试报告》。
- 自动化测试脚本库(含200+测试用例)。
-
验收标准:
- 通过国家工业信息安全发展研究中心的信创兼容性认证。
- 客户满意度评分≥9.0分(满分10分)。
项目负责人签字:_________________
铁路局集团代表签字:_________________
日期:2025年XX月XX日
备注:本项目代码已通过华为云DevCloud信创代码扫描,无中高危漏洞,符合《铁路行业信息化安全规范》要求。
复制插件目录

引入插件文件
UEditor 1.4.3.3示例
注意:不要重复引入jquery,如果您的项目已经引入了jq,则不用再引入jq-1.4

在工具栏中增加插件按钮
//工具栏上的所有的功能按钮和下拉框,可以在new编辑器的实例时选择自己需要的重新定义
toolbars: [
[
"fullscreen",
"source",
"|",
"zycapture",
"|",
"wordpaster","importwordtoimg","netpaster","wordimport","excelimport","pptimport","pdfimport",
"|",
"importword","exportword","importpdf"
]
]
初始化控件

var pos = window.location.href.lastIndexOf("/");
var api = [
window.location.href.substr(0, pos + 1),
"asp/upload.asp"
].join("");
WordPaster.getInstance({
//上传接口:http://www.ncmem.com/doc/view.aspx?id=d88b60a2b0204af1ba62fa66288203ed
PostUrl: api,
//为图片地址增加域名:http://www.ncmem.com/doc/view.aspx?id=704cd302ebd346b486adf39cf4553936
ImageUrl: "",
//设置文件字段名称:http://www.ncmem.com/doc/view.aspx?id=c3ad06c2ae31454cb418ceb2b8da7c45
FileFieldName: "file",
//提取图片地址:http://www.ncmem.com/doc/view.aspx?id=07e3f323d22d4571ad213441ab8530d1
ImageMatch: ''
});//加载控件
注意
如果接口字段名称不是file,请配置FileFieldName。ueditor接口中使用的upfile字段

点击查看详细教程
配置ImageMatch
匹配图片地址,如果服务器返回的是JSON则需要通过正则匹配
ImageMatch: '',
配置ImageUrl
为图片地址增加域名,如果服务器返回的图片地址是相对路径,可通过此属性添加自定义域名。
ImageUrl: "",
配置SESSION
如果接口有权限验证(登陆验证,SESSION验证),请配置COOKIE。或取消权限验证。
点击查看配置教程
功能演示
编辑器界面

导入Word文档,支持doc,docx

导入Excel文档,支持xls,xlsx

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

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

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

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

上传网络图片

1130

被折叠的 条评论
为什么被折叠?



