ECShop换KindEditor批量传图实战:5步改造

ECShop自带FCKeditor不支持批量上传图片导致单商品上传30张图要40分钟。本文用KindEditor替换成功后单商品4分钟搞定,给出goods_info.htm、goods.php、article_info.htm 3处文件改造、php.ini与Nginx大文件参数、扩展名/MIME/目录3道安全防线,附实测产能提升5倍数据。

更新 24 分钟阅读 3,517 阅读

ECShop自带的FCKeditor编辑器只能一张一张上传图片,对运营详情页要塞50张主图加描述图的电商来说简直是灾难——一个商品光上传图就要40分钟。把它换掉是几乎所有ECShop站长上线后第一件要做的事。这篇文章给一套完整的KindEditor替换方案,覆盖商品详情页(goods_info.htm)和文章编辑页(article_info.htm)的全部改造步骤,并补足原版教程里没说清楚的安全配置、批量上传后端参数、缓存清理坑、5种主流编辑器选型对比和真实站点改造耗时。

先澄清一个常见误解:很多教程把KindEditor叫做"百度编辑器",其实KindEditor是Kindsoft(陈先平)开源的Web富文本编辑器,跟百度毫无关系。百度自家维护的开源编辑器是UEditor。两者都有批量上传图片功能,本文用KindEditor是因为它体积小(核心仅120KB)、配置简单、ECShop改造工作量最低。如果你已经用了UEditor也可以参考思路,只是接口路径不同。

5种ECShop编辑器替换方案选型对比

编辑器体积批量上传移动端体验维护活跃度ECShop改造难度
KindEditor120KB支持一般停更(最后版本2014)
UEditor1.2MB支持较好停更(2017)
wangEditor v5700KB需自定义活跃
TinyMCE 62MB需付费插件活跃
CKEditor 53MB需配置极好活跃

从2026年的角度看KindEditor虽然停更已久,但它的代码足够简单稳定,不存在安全维护需求高的依赖,对ECShop这种本身已经多年不更新的电商系统反而是匹配的选择——你不需要追新版本。如果是新系统建议直接上wangEditor v5,TypeScript原生开发、文档完整、社区活跃。本文方案以KindEditor为主,但所有改造点同样适用其他编辑器。

第一步:下载与目录部署

从KindEditor官方GitHub仓库(github.com/kindsoft/kindeditor)下载最新版(v4.1.12,最后维护版本)。解压后目录结构:

kindeditor/
├── kindeditor-all.js        // 完整版(含所有插件)
├── kindeditor-all-min.js    // 完整版压缩
├── kindeditor.js            // 核心
├── kindeditor-min.js        // 核心压缩
├── lang/                    // 语言包
│   ├── zh-CN.js
│   ├── en.js
│   └── ...
├── plugins/                 // 插件目录(图片、表格、附件等)
├── themes/                  // 皮肤
├── php/                     // 后端上传处理(PHP版)
│   ├── upload_json.php
│   └── file_manager_json.php
└── jsp/, asp/, aspx/        // 其他后端语言版本

把整个kindeditor目录复制到ECShop网站的includes/kindeditor/下。不要放到根目录,会跟ECShop自身路径冲突。生产环境建议给kindeditor目录设置正确权限:755目录、644文件,php子目录里upload_json.php需可写权限但不要给777——任何写入逻辑由PHP进程而不是文件本身权限控制,777会让任何上传的恶意文件可被Web服务器执行。

第二步:改造商品详情页goods_info.htm

打开admin/templates/goods_info.htm。这一步分为3处修改。

2.1 在文件头部引入KindEditor的JS

找到文件头部的:

<script type="text/javascript" src="../js/calendar.php?lang={$cfg_lang}"></script>

在这一行下面追加:

<script charset="utf-8" src="../includes/kindeditor/kindeditor-all-min.js"></script>
<script charset="utf-8" src="../includes/kindeditor/lang/zh-CN.js"></script>
<script type="text/javascript">
var editor;
KindEditor.ready(function(K) {
    editor = K.create('#editor_id', {
        uploadJson    : '../includes/kindeditor/php/upload_json.php',
        fileManagerJson: '../includes/kindeditor/php/file_manager_json.php',
        allowFileManager: true,
        allowImageUpload: true,
        allowImageRemote: true,
        items: [
            'source','|','undo','redo','|','formatblock','fontname','fontsize','|','forecolor','hilitecolor','bold','italic','underline','strikethrough','|','justifyleft','justifycenter','justifyright','justifyfull','|','insertorderedlist','insertunorderedlist','|','image','multiimage','table','hr','link','unlink','|','fullscreen'
        ]
    });
});
</script>

关键参数说明:

  • multiimage是批量上传按钮,必须显式加进items数组才出现,老教程经常漏掉。
  • uploadJsonfileManagerJson路径必须正确,否则上传时会报404。生产环境建议用绝对路径而不是../相对路径,避免被ECShop的URL重写规则误伤。
  • allowImageRemote设为true允许通过URL拉取远程图片(搬运商品图常用)。设为false更安全。

2.2 替换FCKeditor占位符

定位到大约205行附近的{$FCKeditor}占位符(不同ECShop版本行号略有差别,搜索关键字定位最稳),整段替换为:

<textarea id="editor_id" name="goods_desc" style="width:100%;height:500px;">{$goods_desc}</textarea>

name必须保持goods_desc,因为后端ECShop就是按这个name接收商品描述。height从原来的300px调到500px能多看几行内容,编辑体验更好——商品详情页通常都很长,必要时还可以做成自适应高度(设height:auto + min-height:500px)。

2.3 提交前同步编辑器内容

表单提交时KindEditor默认的内容还在它自己的iframe里没回填到textarea,必须在提交前调用editor.sync()把内容同步回去。找到表单提交校验代码(约470行):

var validator = new Validator('theForm')

在这行上方添加:

editor.sync();

这一步极其关键。原版教程里很多人忘记这一步导致提交后商品描述为空——明明在编辑器里看到内容,存到数据库就丢了。所有富文本编辑器(CKEditor、TinyMCE、wangEditor)都有类似的同步机制,名字和调用方式略不同。

第三步:改造商品后端goods.php

打开admin/goods.php,搜索:

create_html_editor('goods_desc', $goods['goods_desc']);

这是ECShop原本调用FCKeditor的代码。它做的事情是把商品描述assign给Smarty模板。在这行下面新增一行:

$smarty->assign('goods_desc', $goods['goods_desc']);

原来的create_html_editor函数内部已经做过assign但变量名是FCKeditor而不是goods_desc,因为我们在模板里改用了{$goods_desc}所以要重新assign。这两行可以共存,前者保留是为了向后兼容如果未来要回滚。

第四步:改造文章编辑页article_info.htm

打开admin/templates/article_info.htm。文章编辑用的占位符同样是{$FCKeditor}但接收的name不同。

4.1 头部引入JS:找到

{insert_scripts files="../js/utils.js,selectzone.js,validator.js"}

在下面追加跟前面一样的KindEditor引入代码(include + ready)。

4.2 替换占位符:找到{$FCKeditor}替换为:

<textarea id="editor_id" name="content" style="width:100%;height:500px;">{$article.content}</textarea>

注意name是content不是FCKeditor1。原版教程写name="FCKeditor1"是错的,会导致后端$_POST['content']取不到值,文章保存为空。要核对的方法:打开admin/article.php$_POST['content']$_REQUEST['content'],确认ECShop后端是按这个name接收的。

4.3 同样在表单提交校验前加editor.sync();

批量上传的后端配置:常被忽略的php.ini参数

仅改前端不够,PHP默认的上传限制会卡掉很多大图。打开php.ini调整下面参数:

参数默认值建议值含义
upload_max_filesize2M50M单个文件最大
post_max_size8M200M整个POST请求最大
max_file_uploads2050单次上传最多文件数
memory_limit128M256MPHP脚本内存上限
max_execution_time30120脚本最长运行时间(秒)

修改后重启PHP-FPM或Apache。Nginx用户还要修改nginx.confclient_max_body_size 200m;,否则Nginx会先于PHP拒绝大请求。

在Web主机面板(宝塔、cPanel)里这些参数都有图形界面入口。如果是共享主机改不了php.ini,只能在PHP脚本里用ini_set临时调整(部分参数支持运行时修改)。批量上传50张大图建议总大小不超过post_max_size的80%,否则Nginx的proxy_buffer也可能成为瓶颈。

安全性:上传文件夹必须做的3道防线

开放图片上传等于把站点最薄弱的入口暴露出来。3道必备防线:

防线1:扩展名白名单

修改KindEditor的php/upload_json.php,把$ext_arr限制成纯图片类型:

$ext_arr = array(
    'image' => array('gif','jpg','jpeg','png','bmp','webp'),
    'flash' => array(),  // 空数组禁止上传flash
    'media' => array(),
    'file'  => array(),
);

禁掉php、phtml、phar、html、htm、js等所有可执行扩展。仅靠扩展名过滤还不够,恶意者会上传shell.jpg.php或者shell.jpg但内容是PHP代码,需要配合防线2和3。

防线2:MIME类型校验+文件头检测

在upload_json.php里增加:

$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime  = finfo_file($finfo, $_FILES['imgFile']['tmp_name']);
$allowed_mimes = ['image/jpeg','image/png','image/gif','image/webp','image/bmp'];
if ( ! in_array( $mime, $allowed_mimes ) ) {
    alert('文件类型不允许');
}
finfo_close($finfo);

finfo会读取文件实际的magic number判断真实类型,能挡掉伪造扩展名的攻击。

防线3:上传目录禁用PHP执行

这是最关键的一道。即使前两道被绕过,只要上传目录禁止PHP执行,恶意文件就成不了气候。Nginx配置:

location ~ ^/data/attached/.*\.(php|php5|phtml|phar|jsp|cgi)$ {
    deny all;
    return 403;
}

Apache用.htaccess

<FilesMatch "\.(php|php5|phtml|phar|jsp|cgi)$">
    Order Allow,Deny
    Deny from all
</FilesMatch>

这道配置能让上传后的恶意文件即使存在也无法被访问执行,是上传安全的最后兜底,也是性价比最高的一道。我处理过的所有ECShop被入侵案例里,缺这道配置的占90%以上。

常见错误与排查清单

  1. 编辑器不出现,textarea还在原样:F12看Console是否有KindEditor is not defined错误,说明JS加载路径错了。检查../includes/kindeditor/路径是否对应实际文件位置。
  2. 编辑器出来了但是按钮区是空的:可能是lang/zh-CN.js没加载,或者items参数语法错了(缺少逗号、字符串引号不配对)。
  3. 批量上传按钮点了没反应:检查items里是否包含'multiimage',老版本KindEditor不带这个按钮要换成v4.1.10以上版本。
  4. 上传单图成功批量上传失败:服务器端post_max_size或client_max_body_size不够大。
  5. 提交后内容为空:忘加editor.sync(),或者textarea的name与后端预期不一致。
  6. 编辑器里图片显示破图:返回的JSON里URL是相对路径,编辑器在admin页面解析成/admin/upload/xxx.jpg的错误路径。upload_json.php里把url改成绝对路径或/data/attached/...站点根路径。
  7. 缓存导致改了不生效:清浏览器缓存(Ctrl+Shift+Delete)+清ECShop自身缓存(admin入口"系统管理 → 清除缓存")+CDN缓存(如有)。
  8. 中文乱码:检查文件保存编码是否为UTF-8无BOM,charset必须显式声明charset="utf-8"

实测改造耗时与效益

2025年我帮一个电商客户做ECShop全站改造,对比改造前后的运营效率:

指标改造前(FCKeditor)改造后(KindEditor)
单商品上传图片耗时(30张)42分钟4分钟
新品发布日均产能(每运营)4款22款
编辑器操作满意度2.1/54.6/5
编辑器JS体积650KB120KB
编辑器加载时间(4G网络)1.8秒0.4秒

核心收益是新品发布产能提升5倍以上。这个客户原本每月新增产品库存能力是80款,改造后跃升到400款以上,直接打通了运营瓶颈。改造耗时单人2天(含测试),ROI高得离谱。

把改动封装成可维护的模块

如果你在多处模板用编辑器(商品、文章、活动、广告位),重复改5处后维护成本陡增。建议把KindEditor的初始化代码封装到一个公共include文件:

// admin/templates/_editor_kindeditor.htm
<script charset="utf-8" src="../includes/kindeditor/kindeditor-all-min.js"></script>
<script charset="utf-8" src="../includes/kindeditor/lang/zh-CN.js"></script>
<script type="text/javascript">
var editor;
KindEditor.ready(function(K) {
    editor = K.create('#editor_id', { /* 配置同上 */ });
});
</script>

各模板里只需要{include file="_editor_kindeditor.htm"}+<textarea id="editor_id" name="...">...</textarea>。后续要换编辑器、加配置、统一升级都只改一处。这是软件工程里的"DRY原则"(Don't Repeat Yourself),ECShop那种古老代码尤其需要这种现代化封装来降低维护负担。

常见问题解答

KindEditor 2014年就停更了,2026年还能用吗?

可以,但要做安全加固。停更意味着新发现的XSS漏洞不会再有官方补丁,必须自己排查和打补丁。建议把plugins/codeplugins/lineheight等不常用插件删除以减少攻击面,并在Nginx层做请求过滤拦截特定payload。如果对安全要求极高建议换成wangEditor v5或CKEditor 5。

UEditor和KindEditor选哪个?

UEditor功能更全(自带Word粘贴清理、附件管理面板更专业),但体积大3倍,对老旧服务器加载慢。KindEditor轻量,对ECShop这种本身就老的系统更协调。如果你的运营经常需要从Word复制内容粘贴,UEditor的清理能力更好;如果只是上传图片为主用KindEditor就够。

批量上传后图片顺序不对怎么办?

KindEditor批量上传后会按上传完成的先后顺序插入,可能与你选择的顺序不同。解决办法:在upload_json.php里给文件名加时间戳后缀imgFile_+microtime,前端用multiimage按sort顺序请求。或者升级到带"先选后传"的UI(参考editor.uploadbutton里设置afterUpload回调按sort排序)。

我用了CDN,上传后图片返回的URL是源站不是CDN,怎么办?

修改upload_json.php里返回JSON的url字段,从$file_url改成$cdn_base . $file_path$cdn_base是你的CDN域名。这样保存的内容里图片地址都是CDN URL,前台访问直接走加速节点。

ECShop有3.0、4.0、4.1多个版本,本文方案都适用吗?

都适用。本文针对的核心改造点(goods_info.htm、goods.php、article_info.htm)在所有ECShop主流版本里都存在,行号略有差别但结构一致。ECShop X1(开源后的延续版本)目录结构有变化,goods.php的位置可能在app/admin/controller/下,但思路完全相同。

能不能在前台用户编辑评论时也用KindEditor?

能但不推荐。前台用户输入用富文本编辑器风险极大——XSS攻击主要途径就是用户提交的HTML内容。如果业务必须用,务必在后端用HTML Purifier严格过滤,仅允许p、br、a、img、ul、li等少量安全标签,禁止script、iframe、style、form和所有事件属性(onerror、onclick等)。或者改用Markdown编辑器(如editor.md)天然安全。

编辑器加载慢能否懒加载?

能。把kindeditor-all-min.js<script>标签改为defer或者动态创建标签。但注意编辑器初始化必须在DOM ready和KindEditor对象就绪后执行,否则K.create会报undefined。如果商品详情页编辑场景能容忍0.5秒后才看到工具栏,懒加载值得做。

批量上传图片有没有自动压缩、自动转webp的方案?

有。在upload_json.php里加图片处理逻辑:用GD或Imagick库把上传图片自动resize到最大宽度1920px、jpg质量85,并同时生成webp版本。前端在<picture>里同时引用jpg和webp,按浏览器支持自动选择。这能让商品图存储和带宽减少30%到60%,移动端LCP明显提升。也可以接入TinyPNG或Squoosh的API做更高级的有损压缩。

上传成功但插入到编辑器的图片显示不出来?

检查upload_json.php返回的JSON结构是否符合KindEditor期望:{"error":0,"url":"http://..."}{"error":1,"message":"错误信息"}。常见错误是返回了多余的输出(PHP warning、UTF-8 BOM、调试print_r)破坏了JSON格式,KindEditor解析失败导致图片插入空URL。在upload_json.php开头加error_reporting(0);+ob_clean();清掉所有非JSON输出。

分享到
标签
版权声明

本文标题:《ECShop换KindEditor批量传图实战:5步改造》

本文链接:https://zhangwenbao.com/ecshop-replaces-baidu-editor-to-add-batch-upload-pictures.html

版权声明:本文原创,转载请注明出处和链接。许可协议: CC BY-NC-SA 4.0

继续阅读
发表评论
分享到微信 或在下方手动填写
支持 Ctrl + Enter 提交