上个月接到一个单位老站的适配需求,帝国CMS 7.5,站点本身平平无奇,问题是客户要求所有编辑终端切换成信创环境:银河麒麟V10系统,奇安信可信浏览器,后台还要能正常发布Word稿件。原以为就是换个浏览器的事,结果一测就翻车:Word里粘过去的内容,图片全部红叉,上传按钮点了没反应,个别终端连编辑器工具栏都加载不出来。
这个场景在政企和行业单位的迁移项目里太典型了。帝国CMS 7.5这套老系统当年跑在Windows+Chrome/IE上十几年,现在整套环境换到国产CPU、国产操作系统、国产数据库和国产浏览器,原来依赖的浏览器插件、服务端转码组件、数据库方言全部要重新过一遍。这篇文章就把我这轮改造的完整过程写成记录,从问题拆解、前端上传改造、服务端Word转HTML方案,到数据库迁移适配,一次说清楚。正在做帝国CMS信创迁移的PHP后端或前端开发,可以参考这条闭环思路。
1. 信创终端上,Word导入功能到底断在哪几环
做信创适配最怕的不是某个功能不会写,而是对整个链路没有“问题地图”,只能遇到一个bug修一个bug,改到后面越改越乱。我接这个项目之后先没急着动代码,而是把所有环境变量拉出来过了一遍,发现Word导入这条路从浏览器到数据库要穿过四层环境,每一层都存在和原来不一样的变量。
1.1 终端环境变了,跑在浏览器里的逻辑也要跟着变
信创终端上常见的操作系统是银河麒麟、统信UOS这类基于Linux内核的发行版,CPU还分x86、ARM(鲲鹏、飞腾)、龙芯等多种架构。浏览器侧基本是奇安信可信浏览器、360安全浏览器、统信UOS自带的UOS浏览器、红莲花浏览器这几种。
这些浏览器大多基于Chromium内核,但版本通常落后于主流Chrome好几代,而且为了适配国产芯片做过二次编译。带来的直接后果是:老项目里那些针对特定浏览器写的私有API、依赖IE行为的写法,以及使用了淘汰插件的上传控件,在信创浏览器上要么静默失效,要么直接报错。Word导入这类功能,前端恰恰是重灾区。
1.2 服务端不再是Windows,PHP版本你也未必能控制
我接手前一直以为Word导入的服务端逻辑是PHP处理的,问题应该不大。后来排查才发现,老站当年在Windows服务器上跑,Word文档转HTML这段实际上是通过PHP调用Windows COM组件,启动本机Word应用程序来完成转换的。这套逻辑在Windows上能用,换成国产化的Linux服务器环境之后,COM对象根本不存在,转换接口等于直接被废掉。
另外还有一个隐藏变量是PHP版本。帝国CMS 7.5是多年前的版本,老服务器上跑的是PHP 5.6,信创环境的服务器预装或要求使用的往往是PHP 7.4甚至PHP 8.0。帝国CMS 7.5在PHP 8下会暴露一堆废弃函数的兼容问题,像 create_function()、each() 这类已经被移除,Word导入链路里但凡调用到这些函数,后端就直接白屏或500。
1.3 数据库从MySQL切到国产库,SQL层也有变化
政企项目做信创验收时,数据库一般会被要求从MySQL替换成达梦(DM8)或人大金仓(KingbaseES)。帝国CMS默认只适配MySQL,很多SQL写法都有MySQL方言的味道,比如 AUTO_INCREMENT、LIMIT 分页、GROUP BY 的非严格行为等。数据库一换,Word导入过程中把标题、正文、图片路径写库的那一瞬间就会出现问题,轻则插入失败,重则整条记录写不进去。
这三层问题不是独立的,实际排查时它们会互相干扰。所以做适配之前先在心里拉一张链路图,后面每一步改动都知道自己在改哪一环,为什么要改。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 帝国CMS 7.5的Word导入链路拆解:从粘贴到入库要过五关
我习惯把问题说得更具体一点。所谓Word导入功能,在帝国CMS 7.5的后台场景里通常不是用户上传一个docx文件那么简单,最常见的是编辑在Word里排版好了,直接复制粘贴到后台编辑器的内容区,然后保存发布。这中间要过五道关卡,每一关都可能因为信创环境的变化而断掉。
2.1 第一关:Word内容从剪贴板进编辑器
编辑在Word中复制内容后,剪贴板里同时存在两种格式:纯文本和带格式的HTML片段。编辑器粘贴时,如果直接使用浏览器默认的粘贴事件,拿到的是系统翻译过的HTML,Word里的表格、样式、图片引用会被打乱。大多数CMS的编辑器会监听 paste 事件,自定义处理剪贴板里的HTML。这一步在信创浏览器上出问题,多半是编辑器脚本里用了某些老的事件模型。
比如有些老编辑器会判断 window.clipboardData,这是IE的私有实现,在国产化浏览器里根本不存在。兼容写法是同时读取 event.clipboardData 和 window.clipboardData,用能力检测而不是浏览器类型判断。
2.2 第二关:图片如何从Word文档里剥离出来
Word里贴进来的图片,在剪贴板HTML中通常以两种形态出现:一种是被转换为base64字符串直接嵌在HTML里,另一种是引用一个本地文件路径或者临时Blob地址。帝国CMS的编辑器拿到数据后,需要把图片提取出来,单独上传到服务器,再把HTML里的图片地址替换成服务器URL。
这一步在信创环境下的典型问题是:编辑器判断到某些图片协议(比如 file:// 或 blob:)时,会尝试用IE的 execCommand('insertImage') 插入,或者跳过后台上传流程,最终保存后图片链接指向本地路径,前端自然显示红叉。
2.3 第三关:上传动作是否依赖ActiveX/Flash
这是历史包袱最重的一环。老一代CMS前台做过不少基于ActiveX控件的多文件上传组件,也有的用Flash上传插件。这类组件在Windows+Chrome时代就已经不好用了,在信创环境的国产化浏览器里更是彻底不可用。没有Flash插件,没有ActiveX插件注册表,点击上传按钮通常会弹出一个加载失败的对话框,或者干脆没有任何反应。
如果是这种情况,前端必须整个换成基于HTML5标准的上传方案,使用 FormData 和 XMLHttpRequest,这是所有现代浏览器都支持的能力,信创浏览器也一样。
2.4 第四关:PHP接收上传与文档转码
上传接口到达PHP后端后,老系统如果混入了Windows COM转换逻辑,这段就是必炸点。即使没走COM,有些项目会在后端用 exec() 调用系统里的转换工具,比如Windows下调用 pandoc.exe 或Office命令行,这些在Linux环境下也要重新选型。
另外,帝国CMS 7.5的代码对PHP版本敏感。它内部大量使用老式写法,在PHP 7.4下还能跑,在PHP 8.0下就可能因为 each() 被移除而直接报致命错误。所以后端改造的第一件事是把PHP版本锁定在一个团队测试过的范围内,或者先做一轮老函数替换。
2.5 第五关:入库的字段和字符集
正文内容经过编辑器处理后是一大段HTML,帝国CMS会把这段HTML放在内容表的 newstext 字段里,标题、关键字等字段单独存储。数据库换成达梦或金仓后,字段类型映射、字符集、自增主键的写法都要重新确认。这块我在第5章详细展开,这里先记住一个结论:内容表的大文本字段,MySQL里的 MEDIUMTEXT 到达梦里通常要映射成 CLOB,而 CLOB 在SQL书写和程序读取时都有一些额外注意点。
把五关画出来之后,改造顺序其实就很清楚了:先保证前端能在信创浏览器里把Word变成HTML并成功上传图片,再保证后端能把文档转换成可入库的HTML,最后保证HTML能顺利写进国产数据库。
3. 前端改造:用H5标准上传替换ActiveX和Flash依赖
前端部分是整个Word导入功能在信创环境里最直接、最容易出问题的环节,也是我能给到最多具体操作建议的地方。改造不是把一个上传组件换掉就完事,更关键的是把代码里那些隐性的浏览器私有依赖清理干净。
3.1 先给前端代码做个“排雷”检查清单
动手之前,我建议先把帝国CMS后台用到的编辑器、上传组件、公共JS文件全局搜一遍,重点看以下几类写法:
| 风险代码写法 | 原因 | 信创浏览器上的表现 |
|---|---|---|
window.clipboardData |
IE私有API | 获取不到剪贴板内容,粘贴无效 |
ActiveXObject 实例化 |
IE插件对象 | 直接抛出未定义错误 |
swfobject.embedSWF 相关 |
Flash依赖 | Flash插件不存在,上传无响应 |
document.all 判断IE |
老式浏览器检测 | 逻辑误判,走了错误分支 |
使用 Sizzle 或极老版本jQuery的某些API |
内部实现依赖已废弃行为 | 编辑器加载中断 |
new Image() 赋值后不设置 crossOrigin |
跨域图片处理 | 图片抓取失败 |
这类排雷用IDE全局搜索或者命令行 grep 都行,重点是心里有数:到底有多少地方在依赖已经被时代淘汰的接口。
3.2 上传组件换成FormData+XMLHttpRequest
不管原来用的是ActiveX还是Flash控件,最终都要统一替换成一个标准的H5上传函数。信创浏览器对H5标准的支持是可靠的,这也是我在这个项目里最推荐的做法。
javascript复制function uploadWordImage(file) {
const formData = new FormData();
formData.append('file', file);
formData.append('action', 'wordimage');
return new Promise(function (resolve, reject) {
const xhr = new XMLHttpRequest();
xhr.open('POST', '/e/action/wordupload.php', true);
xhr.onload = function () {
if (xhr.status === 200) {
try {
resolve(JSON.parse(xhr.responseText));
} catch (e) {
reject(new Error('上传接口返回格式异常'));
}
} else {
reject(new Error('上传失败,HTTP状态码:' + xhr.status));
}
};
xhr.onerror = function () {
reject(new Error('网络异常,上传请求未到达服务器'));
};
xhr.send(formData);
});
}
这个函数的逻辑很简单,但有几个细节值得注意。第一,action 这个参数可以放进FormData,也可以在URL上带,我习惯放FormData里,避免GET参数被浏览器或中间件截断。第二,后端返回格式必须是JSON,如果是转码任务耗时较长,后端应该先返回一个 task_id,前端用轮询或 setTimeout 定时查结果,不要让用户点一下按钮干等十秒没反应。
3.3 处理Word粘贴时的图片自动上传
Word粘贴过来的图片,一般会以base64字符串出现在粘贴的HTML中。如果我直接把这段base64内容提交入库,会给数据库造成很大压力,而且将来页面加载也会很慢。正确做法是监听编辑器的粘贴事件,把base64图片提取出来,转成Blob文件再用上面的 uploadWordImage 上传,最后用服务器URL替换HTML里的原图数据。
javascript复制editor.addListener('paste', function (t, e) {
const clipboardData = e.clipboardData || window.clipboardData;
if (!clipboardData || !clipboardData.items) {
return;
}
const items = clipboardData.items;
for (const item of items) {
if (item.kind === 'file' && item.type.indexOf('image') === 0) {
const file = item.getAsFile();
e.preventDefault();
uploadWordImage(file)
.then(function (res) {
if (res && res.url) {
editor.execCommand('insertHtml', '<img src="' + res.url + '" alt="word-image" />');
}
})
.catch(function (err) {
alert('Word图片上传失败:' + err.message);
});
break;
}
}
});
这段代码是我在实际项目里经过几轮调整后的最终形态。核心逻辑是:优先从 clipboardData.items 里找图片,拿到File对象后立刻上传,上传成功再把图片插回编辑器。这么做的好处是,粘贴步骤和上传步骤彻底解耦,后续不管换哪个编辑器,这段逻辑都可以复用。
如果用UEditor这类编辑器,还有更省事的方案:开启它的wordimage配置,然后让后台上传接口按UEditor要求的JSON格式返回。我上面手写的这套则更底层,对帝国CMS的兼容性更可控,如果你不想被编辑器框架绑定,可以直接照着改。
3.4 用能力检测而不是UA判断来做兼容分支
做信创浏览器适配时,最忌讳的就是根据 navigator.userAgent 判断浏览器类型来写分支,因为信创浏览器经常做二次包装,UA字符串不一定真实反映内核能力,而且你无法穷举所有版本的国产浏览器。
我采用的标准做法是能力检测。比如判断是否支持FormData,直接 if (window.FormData && window.XMLHttpRequest),判断是否支持剪贴板文件,直接 if (window.ClipboardItem || 'items' in DataTransfer.prototype)。这样不管客户端是什么操作系统、什么浏览器,只要它实现了标准能力,代码就能跑通。
这个原则贯穿整个前端改造,也特别适合写进信创项目的《前端开发规范》里:不依赖具体的浏览器品牌,不依赖OS级别的插件能力,所有分支都围绕运行时实际能力做判断。
4. 服务端转换:把Word解析从Windows搬到Linux容器
前端把Word内容成功转成HTML并发给了后端,后端还要处理一个更麻烦的问题:真正上传一个 .docx 或 .doc 文件到服务器时,服务端怎么把Word二进制解析成HTML?以前用Windows COM的思路必须抛弃,在信创Linux环境下要用可运行在国产CPU架构上的纯服务端方案。
4.1 为什么老方案在信创服务器上直接失效
老网站如果通过PHP直接操作Word文档,最常见的手段是安装Office后,用PHP的COM类创建一个 Word.Application 对象,让Word自己打开文档再另存为HTML。这个方案在Windows服务器上确实是可行的,但信创服务器是国产Linux系统,根本不存在COM组件机制,更不可能在服务器上安装Microsoft Office。
还有一个容易忽略的问题:老方案还会把Word文档里的字体、间距、页眉页脚等全部转进HTML,导致前台页面样式混乱。所以从产品角度讲,服务端至少要做一个“内容清洗”,把Word的多余格式过滤掉,只保留段落、标题、图片、表格等基本元素。
4.2 用LibreOffice headless做Doc/Docx转HTML
在Linux服务器上做Word转HTML,我目前用过最可靠、最不折腾的方案是LibreOffice的headless模式。它没有图形界面,不用启动完整办公套件,一个命令就能把文档转成HTML或其他格式。最关键的是它支持x86和ARM架构,银河麒麟、统信UOS服务器版上都能装。
安装命令因发行版而异:
bash复制# 银河麒麟V10 / 中标麒麟(yum系)
yum install -y libreoffice-headless libreoffice-writer
# 统信UOS服务器版 / Debian系
apt install -y libreoffice-writer --no-install-recommends
如果服务器是ARM架构(鲲鹏、飞腾),直接从麒麟或统信的软件源里安装即可,这些源里已经包含了对应的ARM版LibreOffice,不用自己编译,这点比我预想的要省事。
安装完成后,转换命令长这样:
bash复制soffice --headless --convert-to html:HTML --outdir /data/wwwroot/word_temp /data/wwwroot/upload/202501/sample.docx
执行成功后,会在输出目录生成一个 sample.html。这个HTML里嵌着的图片默认是引用一个同目录生成的文件夹里的图片文件,还是将图片以base64形式内嵌,取决于HTML过滤器参数。如果希望图片外链,需要在转换参数里额外控制,否则默认行为可能不一样。我实践中的做法是:先把文档转成HTML,再用一个PHP脚本扫描HTML里的图片引用,把图片移动到帝国CMS的附件目录,再替换链接。
4.3 PHP调用转换服务,并处理并发与中文编码
PHP侧调用转换命令,方法很直接:用 exec() 或 shell_exec() 执行 soffice 命令。但这里有几个必须处理的坑。
第一个坑是环境变量。LibreOffice需要一个正常的HOME目录,否则可能报错。PHP执行时默认用户可能是 www 或 nginx,执行命令前必须设置HOME到可写目录:
php复制function wordToHtml($srcPath, $outDir) {
putenv('HOME=' . sys_get_temp_dir());
$src = escapeshellarg($srcPath);
$out = escapeshellarg($outDir);
$cmd = "soffice --headless --convert-to html:HTML --outdir {$out} {$src} 2>&1";
exec($cmd, $output, $code);
if ($code !== 0) {
throw new RuntimeException('Word转换失败:' . implode("\n", $output));
}
$baseName = pathinfo($srcPath, PATHINFO_FILENAME);
return rtrim($outDir, '/') . '/' . $baseName . '.html';
}
第二个坑是并发。如果同时来了多个转换请求,LibreOffice会启动多个进程,内存占用非常快,服务器一卡,所有转换都超时。我项目里用的办法是加一个简单的文件锁,让同一时间只有一个转换任务在跑:
php复制$lockFile = sys_get_temp_dir() . '/word_convert.lock';
$fp = fopen($lockFile, 'w');
flock($fp, LOCK_EX);
try {
$htmlPath = wordToHtml($srcPath, $outDir);
} finally {
flock($fp, LOCK_UN);
fclose($fp);
}
第三个坑是中文文件名。上传的文件名如果是“年度总结报告.docx”,转换后生成HTML文件名也会带中文,PHP读取时如果文件系统字符集和PHP字符集不一致,很容易出现 file_exists 判断失败。我的处理方法是上传后立刻重命名为纯字母数字的临时文件名(比如 W20250123120001.docx),转换完成后再把HTML里的标题内容提取出来,这样能绕开绝大多数文件名编码问题。
4.4 WPS Office for Linux 作为备选方案
对接信创项目时还可能遇到一种情况:客户明确要求优先使用WPS Office,这时候服务端也可以装WPS Office for Linux版本,提供命令行转码接口。WPS对中文文档的排版还原度更好,一些复杂表格和公文格式不会丢。不过WPS的Linux服务版授权和命令行工具使用的成熟度不如LibreOffice,我一般是默认上LibreOffice,如果客户验收时有明确的WPS要求再切换或者并行部署。
还有一个思路是容器化部署。把LibreOffice封装进一个轻量Docker镜像,部署到国产化服务器上,这样既不用在宿主机装一堆依赖,也能通过容器资源限制控制并发时的内存。服务器的容器运行时如果是信创定制的,也兼容标准OCI镜像,整体落地阻力不大。
5. 数据库切换:帝国CMS从MySQL迁到达梦/金仓的字段与语法适配
前端和服务端的问题解决了,Word最终要落库。这一步在信创项目里很容易被低估,总觉得数据库不都是SQL吗,实际迁移时SQL方言的差异会让你改到怀疑人生。帝国CMS这么多年深度绑定MySQL,迁到达梦或者人大金仓要过的坎,我来列一份可以直接参考的清单。
5.1 帝国CMS对MySQL的习惯性依赖点
帝国CMS的默认表结构里,内容表有个大文本字段 newstext,也就是正文HTML,MySQL中类型是 MEDIUMTEXT。另外所有主键字段基本都用 int auto_increment,配合MySQL的自增语法。这两个点在达梦和人大金仓里都需要改写,一旦表结构迁移不过去,后面一切都白搭。
还有SQL写法。帝国CMS的模型字段、标签、SQL查询里大量用了MySQL专属语法,最常见的包括:
limit 0,10这种分页写法,MySQL里是从第0行开始取10条,在达梦和人大金仓里虽然也支持LIMIT,但参数含义和严格模式可能不同,要逐一验证。concat(a, b)做字符串拼接,达梦里虽然兼容了,但某些版本对concat的默认类型转换很敏感。group by的非严格模式,MySQL允许select中带不在group by里的字段,达梦和金仓默认则更严格,报错更频繁。
5.2 常用SQL语法的替换对照表
我结合这次实际项目,整理了一份高频问题对照表,可以直接存下来当迁移参考:
| MySQL写法 | 达梦DM8推荐写法 | 人大金仓KingbaseES推荐写法 | 说明 |
|---|---|---|---|
id INT AUTO_INCREMENT |
id INT IDENTITY(1,1) |
id INT GENERATED BY DEFAULT AS IDENTITY |
主键自增 |
LIMIT 10,20 |
LIMIT 20 OFFSET 10 |
LIMIT 10,20 |
金仓兼容MySQL分页,达梦建议用OFFSET |
MEDIUMTEXT |
CLOB |
TEXT 或 CLOB |
大文本字段,CLOB最稳 |
GROUP BY + 非聚合字段 |
改用 MAX() 或子查询 |
同上 | 严格模式报错 |
INSERT ... ON DUPLICATE KEY UPDATE |
MERGE INTO 或先查后更 |
兼容MySQL可保留 | 达梦改MERGE最稳 |
utf8mb4 字符集 |
默认UTF-8即可 | UTF-8 | 中文编码注意 |
很多人不知道,达梦DM8安装时可以选择MySQL兼容模式,在这个模式下很多MySQL方言能直接解析,大大减少改造成本。人大金仓V8也提供MySQL兼容模式。我的建议是,能开兼容模式就先开,但不要完全依赖它,最终验收时还是要以严格模式下的测试结果为准。
5.3 数据库抽象层要不要改
帝国CMS的数据库操作是封装在底层连接类里的,常规安装默认连接MySQL。如果项目要求直接迁移到国产数据库,有两种路线。
第一种是最小改动路线:数据库层面开启MySQL兼容模式,帝国CMS端继续用mysqli驱动连过去。这种方案的前提是国产数据库的驱动兼容层做得够好,且业务SQL不复杂。我实测下来,基础的内容发布、栏目读取、后台管理都有机会直接跑通,但遇到复杂统计SQL或者动到系统表结构的操作就容易翻车。
第二种是彻底改造路线:在帝国CMS的数据库类上包一层适配器,根据数据库类型选择不同的SQL方言。这个工作量大,而且帝国CMS的代码风格比较老,硬改底层类风险很高。所以我个人推荐的做法是:优先尝试兼容模式,把改造范围控制在建表语句和常见SQL书写习惯上,不轻易动CMS底层类。
5.4 迁移数据时最容易出的编码问题
帝国CMS老站的历史数据一般是UTF-8编码,但也有不少老项目是GBK的。如果源库是GBK,目标库是UTF-8,Word导入的正文里中文字符、全角标点、特殊符号会成为重灾区。
我迁移时做过一次很典型的踩坑:数据从MySQL经工具导入达梦后,前台的新闻正文中所有的中文引号都变成了乱码,看起来像是数据库连接时的字符集设置不对。后来排查发现,是PHP连接达梦时没有执行 SET NAMES UTF8,导致程序写入时把UTF-8的中文按GBK字节解释,落库就乱了。解决办法是在数据库连接初始化时显式设置字符集,帝国CMS底层可以加一行连接后字符集初始化操作。
另外,Word导入的HTML里还经常包含Word特有的符号,比如不间断空格 、全角空格、特殊引号,这些在数据库端不会有问题,但在前端展示时如果页面声明了错误的字符集,会显示成方块或问号。前端页面统一声明 charset="utf-8",同时数据库连接和表结构都统一用UTF-8,才能彻底避免这种隐患。
6. 麒麟/统信UOS上的实测验证与踩坑记录
所有代码改完之后,最后一公里就是在真实信创终端上做一轮系统性的验收。这项工作和普通浏览器测试不一样,同一套前端代码在不同信创终端组合下的表现可能完全不同,如果不列一个测试矩阵,很容易漏测。
6.1 测试矩阵
我建议至少覆盖以下几种常见的信创环境组合,按实际项目要求增删:
| 操作系统 | 处理器架构 | 浏览器 | 测试项 |
|---|---|---|---|
| 银河麒麟V10 | x86_64 | 奇安信可信浏览器 | 编辑器加载、Word粘贴、图片上传、保存发布 |
| 银河麒麟V10 | ARM(鲲鹏/飞腾) | 360安全浏览器 | 编辑器加载、Word粘贴、图片上传、保存发布 |
| 统信UOS 20 | x86_64 | 统信UOS浏览器 | 编辑器加载、Word粘贴、图片上传、保存发布 |
| 统信UOS 20 | ARM(飞腾) | 红莲花浏览器 | 编辑器加载、Word粘贴、图片上传、保存发布 |
每个组合里,我建议把测试用例细化到具体动作,比如:从Word复制三段带图片的正文、直接粘贴到编辑器;再单独测试从Word文件上传docx附件;再测试全文保存后前台预览,重点看正文、配图、表格是否完整。宁可多测几轮,也不要以为某一项过了就全过。
6.2 实测中最常见的三个问题
第一,图片红叉或图片丢失。这个我在文章开头提到过,根因就是前端没有把Word粘贴图片转换成服务器端URL,或者后端接口对base64图片的处理逻辑在信创浏览器上没有触发。改造完前端上传逻辑后,这个问题基本能解决,但测试时要注意:粘贴动作里可能同时包含多张图片,需要确保每张图片都上传成功后再点保存,否则有的图片是临时地址,一刷新就失效。
第二,上传接口假死。信创浏览器对于上传接口的跨域、Cookie携带、请求头设置会比Chrome更严格。我在实测时遇到过一次奇安信浏览器上传图片一直转圈,F12看到请求被拦截,原因是没有携带同源的Session Cookie。解决办法是上传请求中显式设置 withCredentials = true,并且确保接口域名和后台域名完全一致,不要用IP和域名混着访问。
第三,附件下载文件名乱码。前台下载Word附件时,如果用Content-Disposition直接设置中文文件名,不同信创操作系统对RFC 5987编码的支持不一样,导致下载后文件名变成乱码。推荐统一用URL编码后的ASCII文件名,或者使用 filename* 参数格式,兼容性更好。
6.3 给验收和交付的一些建议
最后说点务实的。信创项目验收时,通常不只是看功能能不能用,还会检查开发规范、安全配置、禁用函数清单。所以代码里不要留 eval、create_function、exec 这类高风险函数,除非必要并且已经放到白名单里。LibreOffice转换命令用到的 exec,要精确到只允许执行指定的转换脚本,而不是直接传外部输入拼命令。
交付文档方面,我会把前端改造点、服务端转换流程、数据库迁移记录、测试矩阵和实测结果全部整理成一份交接文档,这样后续有人接手或扩容,也能按同样流程复现。信创环境迭代快,浏览器版本一升级可能又会冒出新老问题,这套文档至少能帮后来人快速定位是哪一层的变化导致的功能回归。
我个人在实际操作中的一个体会是:信创适配没有想象中那么黑科技,绝大多数问题其实都是“老代码依赖了已经被淘汰的浏览器私有能力”,以及“老组件依赖了已经不再提供的操作系统能力”。把问题拆到每一层,用标准化的方案替换掉私有依赖,整套东西就能稳下来。如果你也在做帝国CMS或者同类老PHP系统的信创迁移,建议先把这条Word导入链路跑通,因为它覆盖了浏览器兼容、文件上传、服务端转码、数据库迁移这四大硬骨头,啃下它,其他模块的适配就有了可复用的套路。
