动易SiteFactory是否支持HTML富文本编辑器导入Word?

记一次在Vue2+SpringBoot项目里给UEditor加Word导入功能的奇妙冒险

第一章:需求突降,老板的夺命连环call

"小王啊,咱们后台发布文章那个编辑器得升级了!用户反馈说每次从Word复制内容到编辑器,图片全丢了,格式也乱成一锅粥,你得想办法解决!"电话那头传来老板急促的声音。

我盯着屏幕上那个熟悉的UEditor界面,心里咯噔一下——这不就是传说中的"Word内容搬家"难题吗?作为前端开发,我深知这个需求的坑有多深:Word生成的HTML代码比蜘蛛网还复杂,图片处理更是让人头大。但老板的命令就是圣旨,我立刻开启了我的技术探索之旅。

第二章:开源江湖寻宝记

第一站:CSDN博客的神秘线索

我在CSDN上疯狂搜索,突然被一篇标题为《UEDITOR富文本实现导入WORD功能》的文章吸引。文章里提到一个叫zyOffice的开源组件,号称能完美解决Word导入问题,还支持Vue2!

我火速下载了示例项目,发现这个组件的集成方式相当友好:

  1. 上传zyoffice文件夹到项目
  2. 在工具栏添加插件按钮
  3. 初始化组件时配置转换接口
// 在Vue组件中初始化zyOffice
zyOffice.getInstance({
  word: "http://localhost:8080/api/word/convert",
  wordExport: "http://localhost:8080/api/word/export",
  ui: { render: "wdpst" }
});

最让我惊喜的是,这个组件居然支持信创国产化系统,比如中标麒麟、银河麒麟等,这对我们服务政府客户来说简直是福音!

第二站:GitHub的意外收获

在GitHub上闲逛时,我发现了另一个宝藏项目——WordPaster。这个项目专门解决富文本编辑器粘贴Word内容时的图片上传问题,而且完美支持UEditor!

项目文档里详细介绍了在Vue2中的集成步骤:

  1. 复制WordPaster插件目录到项目
  2. 引入必要的JS文件(注意不要重复引入jQuery)
  3. 在工具栏添加自定义按钮
  4. 初始化WordPaster组件
// 初始化WordPaster组件
const api = window.location.href.substr(0, window.location.href.lastIndexOf("/") + 1) + "api/upload";
WordPaster.getInstance({
  PostUrl: api, // 上传接口地址
  FileFilter: ".doc;.docx", // 支持的文件类型
  MaxSize: 10 * 1024 * 1024 // 最大文件大小10MB
});

第三章:后端SpringBoot的攻坚战

有了前端组件还不够,后端处理才是重头戏。我参考了多个SpringBoot集成UEditor的方案,最终决定采用以下架构:

1. 文件转换服务

使用Apache POI处理Word文档,但发现直接解析复杂格式还是不够完美。于是转向使用Aspose.Words(虽然不是完全开源,但有免费试用版),它对Word格式的保留效果更好。

@RestController
@RequestMapping("/api/word")
public class WordController {
    
    @PostMapping("/convert")
    public ResponseEntity convertWordToHtml(@RequestParam("file") MultipartFile file) {
        try {
            // 使用Aspose.Words转换Word为HTML
            Document doc = new Document(file.getInputStream());
            HtmlSaveOptions options = new HtmlSaveOptions();
            options.setExportImagesAsBase64(false); // 不使用Base64嵌入图片
            options.setResourcesFolder("uploads/images/" + UUID.randomUUID()); // 图片保存路径
            
            // 保存HTML和图片
            String htmlPath = "uploads/html/" + UUID.randomUUID() + ".html";
            doc.save(htmlPath, options);
            
            // 返回处理后的HTML(需要提取图片URL)
            String htmlContent = Files.readString(Paths.get(htmlPath));
            // 这里需要进一步处理htmlContent,替换图片路径为可访问的URL
            
            return ResponseEntity.ok(htmlContent);
        } catch (Exception e) {
            return ResponseEntity.badRequest().body("转换失败: " + e.getMessage());
        }
    }
}

2. 图片上传处理

配置UEditor的上传接口,使用SpringBoot的MultipartFile接收上传的文件:

@RestController
@RequestMapping("/ueditor")
public class UEditorController {
    
    @Value("${file.upload-dir}")
    private String uploadDir;
    
    @PostMapping("/upload")
    public Map uploadImage(@RequestParam("upfile") MultipartFile file) {
        Map result = new HashMap<>();
        
        try {
            // 确保上传目录存在
            File uploadPath = new File(uploadDir);
            if (!uploadPath.exists()) {
                uploadPath.mkdirs();
            }
            
            // 保存文件
            String fileName = UUID.randomUUID().toString() + 
                             file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
            File dest = new File(uploadPath, fileName);
            file.transferTo(dest);
            
            // 返回UEditor需要的JSON格式
            result.put("state", "SUCCESS");
            result.put("url", "/uploads/" + fileName); // 前端可访问的URL
            result.put("title", fileName);
            result.put("original", file.getOriginalFilename());
        } catch (IOException e) {
            result.put("state", "ERROR");
            result.put("message", "上传失败: " + e.getMessage());
        }
        
        return result;
    }
}

第四章:数据库设计的智慧

关于富文本内容的存储,我参考了MySQL富文本存储方案对比,最终选择了以下方案:

  1. 内容表设计
CREATE TABLE article (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200) NOT NULL,
    content TEXT NOT NULL, -- 存储HTML内容
    content_html_path VARCHAR(500), -- 如果内容很大,可以存储HTML文件路径
    create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
    update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
  1. 图片资源表(可选):
CREATE TABLE article_image (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    article_id BIGINT NOT NULL,
    image_url VARCHAR(500) NOT NULL,
    alt_text VARCHAR(200),
    sort_order INT DEFAULT 0,
    FOREIGN KEY (article_id) REFERENCES article(id)
);

对于大多数情况,直接将HTML存储在content字段就足够了。只有当内容特别大时,才考虑将HTML保存为文件,并在数据库中存储文件路径。

第五章:集成测试的酸甜苦辣

成功时刻

经过一周的奋战,终于迎来了第一次完整测试:

  1. 在Word中编写了一篇包含多种格式(标题、加粗、斜体、表格、图片)的文档
  2. 点击UEditor的"导入Word"按钮
  3. 见证奇迹的时刻——所有格式完美保留,图片自动上传并显示!

踩过的坑

  1. 图片路径问题:最初转换后的HTML中图片使用相对路径,导致前端无法显示。解决方案是在后端转换时统一替换为绝对URL。
  2. 跨域问题:前端和后端分离部署时,需要配置CORS。
  3. 样式冲突:Word生成的HTML带有大量内联样式,与UEditor的默认样式冲突。通过自定义CSS重置解决了这个问题。

第六章:最终胜利与经验总结

经过这次冒险,我总结出以下关键点:

  1. 选择合适的工具:zyOffice和WordPaster这两个组件大大简化了开发工作,避免了重复造轮子。
  2. 前后端协作:前端负责展示和交互,后端专注文件处理和存储,分工明确。
  3. 测试的重要性:不同版本的Word、不同浏览器都需要充分测试,确保兼容性。
  4. 性能优化:对于大文件,考虑分块上传和异步处理。

现在,我们的后台编辑器已经能够完美支持Word导入,用户反馈良好。这次经历也让我深刻认识到:在技术世界里,没有解决不了的问题,只有还没找到的解决方案!

最后,附上项目关键依赖版本信息:

  • UEditor: 1.4.3.3
  • zyOffice: 1.5.x
  • WordPaster: 最新版
  • SpringBoot: 2.7.x
  • Aspose.Words: 23.10 (试用版)

希望我的经历能给同样面临这个问题的开发者一些启发和帮助!

复制插件目录

WordPaster插件目录

引入插件文件


	
	UEditor 1.4.3.3示例
	
    
	
	
    
    
    
    
    
    
	
    

注意:不要重复引入jquery,如果您的项目已经引入了jq,则不用再引入jq-1.4
image

在工具栏中增加插件按钮

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

初始化控件

image

        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字段
image
点击查看详细教程

配置ImageMatch

匹配图片地址,如果服务器返回的是JSON则需要通过正则匹配

ImageMatch: '',

点击参考链接

配置ImageUrl

为图片地址增加域名,如果服务器返回的图片地址是相对路径,可通过此属性添加自定义域名。

ImageUrl: "",

点击查看详细教程

配置SESSION

如果接口有权限验证(登陆验证,SESSION验证),请配置COOKIE。或取消权限验证。
参考:http://www.ncmem.com/doc/view.aspx?id=8602DDBF62374D189725BF17367125F3

导入效果

粘贴Word和图片

下载示例

点击下载完整示例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值