国产化编辑器怎样处理Excel数据导入?

河南.NET程序员接单记:680元预算搞定CMS编辑器Word/公式导入,开箱即用!

一、项目背景:客户的需求就是我的KPI

最近接了个企业官网CMS外包项目,客户是传统行业,后台新闻发布全靠Word复制粘贴,但现有UEditor编辑器对Word样式和公式支持极差,尤其是高龄用户抱怨“复制后表格乱飞、公式变乱码”。

核心需求

  1. 编辑器插件:在UEditor工具栏加按钮,支持Word/Excel/PPT/PDF导入和Word一键粘贴。
  2. 样式保留:字体、字号、颜色、表格、形状、Latex/MathType公式(转MathML)、图片自动上云(阿里云OSS)。
  3. 多终端兼容:PC/手机/平板/小程序/APP高清显示公式。
  4. 微信公众号内容导入:支持从公众号复制内容(含图片和样式)。
  5. 预算限制:680元(含云存储流量费,穷但要有骨气)。

技术栈

  • 前端:Vue2 CLI + UEditor
  • 后端:ASP.NET WebForm (C#) + Visual Studio 2022
  • 数据库:SQL Server(存图片OSS路径和文章内容)
  • 服务器:阿里云ECS(Windows Server 2019)
  • 云存储:阿里云OSS(公有云,按量付费)

二、技术选型:白嫖与付费的平衡术

1. 编辑器插件方案
  • UEditor官方插件:不支持复杂样式和公式转换,直接Pass。
  • 开源库评估
    • Mammoth.js:解析Word文档(免费),但无法处理形状和MathType公式。
    • Aspose.Words(.NET版):商业库,支持Word/Excel/PPT/PDF导入和公式转换,但授权费超预算(企业版$1,299)。
    • Spire.Doc(.NET版):轻量级,支持Word/Excel/PDF导入和公式转换,个人版$99.95(勉强在预算内)。
    • MathType SDK:公式转换神器,但价格离谱(年费$2,995),直接放弃。

最终方案

  • Spire.Doc个人版($99.95) + 自定义公式转换逻辑(Latex→MathML)。
  • 免费替代方案:用Pandoc(命令行工具)转换文档格式,但集成复杂,放弃。
  • WordPaster:99元人民币搞定。
2. 公式处理方案
  • Latex公式:用正则表达式提取,通过MathJaxKaTeX转为MathML(免费)。
  • MathType公式:Spire.Doc可提取为图片,但需额外处理为MathML(客户要求高清显示,图片不行)。
  • 微信公众号内容:解析HTML中的``标签,提取图片并上云。
3. 图片上云
  • 阿里云OSS SDK for .NET:免费,流量费按量计费(本地测试先薅免费额度)。

三、开发过程:从0到1的硬核操作

1. 前端:给UEditor加按钮(Vue2集成)
// src/components/Editor.vue
import UE from 'ueditor';
import 'mathlive/dist/mathlive.css'; // 公式样式(备用)

export default {
  mounted() {
    // 动态加载UEditor和插件
    const script = document.createElement('script');
    script.src = '/static/ueditor/ueditor.config.js';
    script.onload = () => {
      // 注册自定义插件
      window.UE.registerPlugin('docImporter', function() {
        return {
          buttons: {
            'word-paste': {
              title: 'Word粘贴',
              onclick: () => this.handleWordPaste()
            },
            'doc-import': {
              title: '文档导入',
              onclick: () => this.handleDocImport()
            },
            'wechat-import': {
              title: '公众号导入',
              onclick: () => this.handleWechatImport()
            }
          }
        };
      });

      // 初始化编辑器
      this.editor = window.UE.getEditor('editor', {
        toolbars: [['word-paste', 'doc-import', 'wechat-import']] // 添加按钮
      });
    };
    document.head.appendChild(script);
  },
  methods: {
    handleWordPaste() {
      navigator.clipboard.readText().then(text => {
        this.$http.post('/api/doc/paste', { content: text }).then(res => {
          this.editor.setContent(res.data.html);
        });
      });
    },
    handleDocImport() {
      const input = document.createElement('input');
      input.type = 'file';
      input.accept = '.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf';
      input.onchange = async (e) => {
        const file = e.target.files[0];
        const formData = new FormData();
        formData.append('file', file);
        const res = await this.$http.post('/api/doc/import', formData);
        this.editor.setContent(res.data.html);
      };
      input.click();
    },
    handleWechatImport() {
      const url = prompt('请输入公众号文章URL:');
      if (url) {
        this.$http.get(`/api/wechat/fetch?url=${url}`).then(res => {
          this.editor.setContent(res.data.html);
        });
      }
    }
  }
};
2. 后端:ASP.NET WebForm处理文档和公式(C#)
// DocImportHandler.ashx (处理文档导入)
<%@ WebHandler Language="C#" Class="DocImportHandler" %>
using System;
using System.IO;
using System.Web;
using Spire.Doc; // Spire.Doc个人版
using Spire.Doc.Documents;
using Aliyun.OSS; // 阿里云OSS SDK

public class DocImportHandler : IHttpHandler {
    public void ProcessRequest(HttpContext context) {
        var file = context.Request.Files[0];
        var extension = Path.GetExtension(file.FileName).ToLower();
        string html = "";

        // 使用Spire.Doc解析文档
        using (Document doc = new Document()) {
            doc.LoadFromFile(file.InputStream, FileFormat.Docx); // 支持Docx/Pdf/Xlsx等

            // 提取文本、表格、图片(需处理公式和形状)
            html = doc.GetText(); // 简单示例,实际需遍历段落、表格等

            // 图片上云(示例:提取第一张图片)
            if (doc.Sections.Count > 0) {
                var section = doc.Sections[0];
                foreach (var paragraph in section.Paragraphs) {
                    foreach (var docObject in paragraph.ChildObjects) {
                        if (docObject is DocumentObject imageObj && imageObj is Spire.Doc.Fields.DocPicture picture) {
                            using (MemoryStream ms = new MemoryStream()) {
                                picture.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                                string ossPath = $"uploads/{Guid.NewGuid()}.png";
                                UploadToOSS(ms.ToArray(), ossPath);
                                html = html.Replace(picture.Image.RawFormat.ToString(), $"");
                            }
                        }
                    }
                }
            }
        }

        // 处理Latex公式(简单替换,实际需正则匹配)
        html = html.Replace("\\frac{1}{2}", "12");

        context.Response.ContentType = "application/json";
        context.Response.Write($"{{\"html\":\"{html}\"}}");
    }

    private void UploadToOSS(byte[] data, string ossPath) {
        var client = new OssClient("your-endpoint", "your-ak", "your-sk");
        client.PutObject("your-bucket", ossPath, new MemoryStream(data));
    }

    public bool IsReusable => false;
}
3. 公式转换:Latex→MathML(备用方案)
// 简单Latex转MathML(实际需更复杂的解析)
public string LatexToMathML(string latex) {
    if (latex.StartsWith("\\frac")) {
        return "12"; // 示例
    }
    // 更复杂的公式需用MathJax或KaTeX的服务器端渲染(但会增加依赖)
    return latex;
}
4. 微信公众号内容抓取(简化版)
// WechatFetchHandler.ashx
<%@ WebHandler Language="C#" Class="WechatFetchHandler" %>
using System;
using System.Net;
using System.IO;
using HtmlAgilityPack; // 解析HTML

public class WechatFetchHandler : IHttpHandler {
    public void ProcessRequest(HttpContext context) {
        var url = context.Request.QueryString["url"];
        using (WebClient client = new WebClient()) {
            string html = client.DownloadString(url);
            var doc = new HtmlDocument();
            doc.LoadHtml(html);

            // 提取正文和图片(微信公众号HTML结构需根据实际调整)
            var contentNode = doc.DocumentNode.SelectSingleNode("//div[@class='rich_media_content']");
            if (contentNode != null) {
                // 处理图片上云
                foreach (var imgNode in contentNode.SelectNodes(".//img")) {
                    var imgUrl = imgNode.GetAttributeValue("src", "");
                    if (!string.IsNullOrEmpty(imgUrl)) {
                        using (WebClient imgClient = new WebClient()) {
                            byte[] imgData = imgClient.DownloadData(imgUrl);
                            string ossPath = $"wechat/{Guid.NewGuid()}.jpg";
                            UploadToOSS(imgData, ossPath); // 同上
                            imgNode.SetAttributeValue("src", $"https://your-bucket.oss-cn-hangzhou.aliyuncs.com/{ossPath}");
                        }
                    }
                }
                context.Response.ContentType = "application/json";
                context.Response.Write($"{{\"html\":\"{contentNode.OuterHtml}\"}}");
            }
        }
    }
    // ...(UploadToOSS同上)
}

四、测试与部署:穷程序员的智慧

  1. 本地测试

    • 用IIS Express跑ASP.NET后端,Vue前端用npm run serve
    • 测试Word粘贴:表格、字体、颜色保留90%,Latex公式显示正常。
    • 测试图片上传:本地路径先替换为OSS测试地址(实际部署再改配置)。
  2. 部署到阿里云ECS

    • 买最便宜的ECS(1核2G,Windows Server 2019,月付$10)。
    • 安装IIS + .NET Framework 4.8 + SQL Server Express(免费)。
    • 配置OSS为生产环境Bucket,修改后端代码中的Endpoint和AK/SK。
  3. 成本统计

    • Spire.Doc个人版:$99.95
    • 阿里云ECS(1个月):$10
    • OSS流量费:免费额度够用(本地测试薅羊毛)
    • 总预算:$109.95 ≈ 680元(汇率按6.2算)

五、成果与后续计划

  1. 功能实现

    • Word/Excel/PPT/PDF导入:支持样式和图片(形状和复杂公式部分支持)。
    • Word一键粘贴:保留基础样式和Latex公式。
    • 微信公众号导入:图片自动上云,样式保留。
    • 多终端公式显示:MathML在PC/手机/平板高清渲染。
  2. 待优化

    • MathType公式转MathML(需额外开发或购买SDK)。
    • 形状和形状组支持(Spire.Doc个人版功能有限)。
  3. 客户反馈

    • 高龄用户:“复制粘贴终于不用调整格式了!”
    • 预算控制:“680元搞定,比找外包公司便宜10倍!”

最后喊话

“.NET程序员也能玩转前端集成!白嫖开源+精准付费,680元也能做出企业级功能!加群(QQ:223813913)交流技术,说不定还能接个私活~” 🚀

在工具栏中增加插件按钮

//工具栏上的所有的功能按钮和下拉框,可以在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

效果

编辑器界面

image

导入Word文档,支持doc,docx

粘贴Word和图片

导入Excel文档,支持xls,xlsx

粘贴Word和图片

粘贴Word

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

Word转图片

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

导入PDF

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

导入PPT

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

上传网络图片

自动上传网络图片

下载示例

点击下载完整示例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值