得差不多就是去年的这个时候,我从原来的单位辞职。原因很简单,二十三四岁,正式一个该奋斗的年纪。虽然家里的条件可以允许自己不必太努力,但是唯有自己拥有赚更多钱的能力,才会让自己觉得心安。思来想去,选择了继续深钻大学的专业,至此我的前端之路也正式开始了。
这一年,从学习到工作,发生了很多的事情。其实自己是一个比较不愿意写东西的人,写博客这个念头也不是一天俩天了,但就是怎么也开展不了。直到前几天,公司的一个项目需求,要用百度的编辑器UEditor替换掉原来的富文本编辑器。一个小小的编辑器,做起来却是一个坑接一个坑,多亏网上的好心的人把自己的经验留下来,才能顺利走下来。感受到这个互联网的共享性和无私性,我也决定成为大家的其中一员,为大家贡献出自己踩每一个坑时的心路历程,希望可以帮助大家,同大家一起共同学习。
话就不多说了,走进正题。UEditor的使用心得。
首先将一下我们的项目架构。本来整个项目是.NET跑的,因为一些原因要转到JAVA上来,所以目前的项目暂定为.NET来跑前端,接口方面由JAVA来提供。因此在使用UEdior时也是一样的。
前期还是比较顺利的,照着官方文档来做。
下载的时候,有点小懵逼,本以为就是一个前端小插件,怎么还分这来多版本,闹啥这是。因为时.net跑的前端,我就下载了.net版
下载的资源包里有demo,还是比较好理解的
简单的来说就是 1.引俩JS 2.body里加一个script标签 3.用getEditor方式创建
跑一下。
这是用在一个新闻审核时的编辑器。所以一开始编辑器就会带有默认值。这里解释下 我为什么没有直接直接将数据放在编辑器的script标签中,如果直接读那么在编辑器中会显示一堆字符串而不是转译后的html,此外有时还会出现内容展示在编辑器外的bug。
如果通过一个textarea先存放数据再用官方文档中的setContent()方法设置编辑器的内容,就完美解决了。看下效果,完美。
注:大家在实际使用的时候会遇见双引号和单引号无法转译的问题。这块我就附个链接http://blog.csdn.net/wanghao3616/article/details/25816747 照这样就可以完美解决了
好了效果实现,重点来了。图片上传。我们具体来分析下代码的流程是怎样的。
UEdior.all.js这个主文件我们先不看,先看uedior.config.js这个配置的文件
这个红框的地方就是后台请求的统一接口。官方文档已经说了,1.4*版本以后已经把所有的后台请求接口合并成一个了,也就是说无论上传还是涂鸦上传都是使用这个接口只是参数action不一样。当然我在实际项目的时候还是任性的把这个接口拆开了。
这样比较直观。其实比较有用的接口就是前俩个。在调试项目的时候发现,编辑器最先会发这个action='config'的请求。这个是设定图片访问规则的一些配置。在写这个接口的时候出现了一些问题,后端返回的数据老是存在问题,所以我就直接用了项目中基于.net的原始接口调用前端这边的config.json文件。其实我觉得这个配置文件放在后端调用返回给前端来最好,因为后端最清楚这些请求地址该怎么写。
因为后端接口没实现,我就把配置文件放在了前端,之后我把配置中的路径都设置为空,这一直接凭后端返回的url就可以直接访问了 不需要再拼了(其实这样一来,配置没啥个用了,存粹走个流程。。)
配置读取完就该上传图片了。因为我们的项目是俩个服务器构成的所以呢就涉及到了跨域的问题。。。这里面是有个坑的。那就是单图和多图的处理是不一样的。
多图比较简单
只要设置好请求头之类普通的跨域常见问题,再调刚才设置的图片上传接口就OK了
单图的话就比较蛋疼了。单文件上传是form提交到iframe,然后iframe里面的内容返回。官方也说了。单文件比较难搞
解决方案就是让后端先将数据反回给.net服务器的一个中转页面,再通过这个中转页面返回来显示,这样就完美解决了单文件的跨域问题。
单文件的请求接口位置 直接修改all.js
1.修改action就是接口
2.干掉这行默认的url
搞完这个就大功告成了。累累累。。。。。
置于后端代码。我这个前端er就不贴了 如果有需要的朋友有需要可以留言和我说。
说实在的纯手写这么多,也不知道又没人会看。第一次,以后也会把质量提起来。自己也会坚持写下去的。加油各位!!!!!!
ue+ueditor+springboot, 实现word文档上传编辑
前言
`前端导入word文档(doc和docx格式都支持),Ueditor富文本回显进行二次编辑,目前ueditor项目archived了,实现两种格式的相关材料相对稀缺。
`解决思路:
1.上传word文件
2.后台读取word内容(图片需要额外处理保存到服务器固定的地址,该地址能让浏览器直接访问),生成html文件
3.后台读取html文件内容返回给前端
一、目标
通过上传word文件,通过后台进行解析回显到前端。
二、代码步骤
后端代码结构:
1.maven依赖库
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>org.apache.poi.xwpf.converter.xhtml</artifactId>
<version>1.0.6</version>
</dependency>
2.vue页面读取ueditor的配置
代码如下:
/**
* 获取UE文件上传配置
* @param request
* @param response
* @throws IOException
*/
@GetMapping(value="/config")
public void ueConfig(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
String urlPrefix=ueProperties.getSavepath();
log.info("urlPrefix="+urlPrefix);
String exec="{\n" +
" /* 上传图片配置项 */\n" +
" \"imageActionName\": \"catcherImage\", /* 执行上传图片的action名称 */\n" +
" \"imageFieldName\": \"upfile\", /* 提交的图片表单名称 */\n" +
" \"imageMaxSize\": 2048, /* 上传大小限制,单位B */\n" +
" \"imageAllowFiles\": [\".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\"], /* 上传图片格式显示 */\n" +
" \"imageCompressEnable\": true, /* 是否压缩图片,默认是true */\n" +
" \"imageCompressBorder\": 800, /* 图片压缩最长边限制 */\n" +
" \"imageInsertAlign\": \"none\", /* 插入的图片浮动方式 */\n" +
" \"imageUrlPrefix\": \"" + urlPrefix + "\", /* 图片访问路径前缀 */\n" +
" \"imagePathFormat\": \"/ueditor/image/{yyyy}{mm}{dd}/\", /* 上传保存路径,可以自定义保存路径和文件名格式 */\n" +
" /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */\n" +
" /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */\n" +
" /* {time} 会替换成时间戳 */\n" +
" /* {yyyy} 会替换成四位年份 */\n" +
" /* {yy} 会替换成两位年份 */\n" +
" /* {mm} 会替换成两位月份 */\n" +
" /* {dd} 会替换成两位日期 */\n" +
" /* {hh} 会替换成两位小时 */\n" +
" /* {ii} 会替换成两位分钟 */\n" +
" /* {ss} 会替换成两位秒 */\n" +
" /* 非法字符 \\ : * ? \" < > | */\n" +
" /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */\n" +
"\n" +
" /* 涂鸦图片上传配置项 */\n" +
" \"scrawlActionName\": \"uploadscrawl\", /* 执行上传涂鸦的action名称 */\n" +
" \"scrawlFieldName\": \"upfile\", /* 提交的图片表单名称 */\n" +
" \"scrawlPathFormat\": \"/ueditor/image/{yyyy}{mm}{dd}/\", /* 上传保存路径,可以自定义保存路径和文件名格式 */\n" +
" \"scrawlMaxSize\": 2048000, /* 上传大小限制,单位B */\n" +
" \"scrawlUrlPrefix\": \"\", /* 图片访问路径前缀 */\n" +
" \"scrawlInsertAlign\": \"none\",\n" +
"\n" +
" /* 截图工具上传 */\n" +
" \"snapscreenActionName\": \"uploadimage\", /* 执行上传截图的action名称 */\n" +
" \"snapscreenPathFormat\": \"/ueditor/image/{yyyy}{mm}{dd}/\", /* 上传保存路径,可以自定义保存路径和文件名格式 */\n" +
" \"snapscreenUrlPrefix\": \"\", /* 图片访问路径前缀 */\n" +
" \"snapscreenInsertAlign\": \"none\", /* 插入的图片浮动方式 */\n" +
"\n" +
" /* 抓取远程图片配置 */\n" +
" \"catcherLocalDomain\": [\"127.0.0.1\", \"localhost\", \"img.baidu.com\"],\n" +
" \"catcherActionName\": \"catchimage\", /* 执行抓取远程图片的action名称 */\n" +
" \"catcherFieldName\": \"source\", /* 提交的图片列表表单名称 */\n" +
" \"catcherPathFormat\": \"/ueditor/image/{yyyy}{mm}{dd}/\", /* 上传保存路径,可以自定义保存路径和文件名格式 */\n" +
" \"catcherUrlPrefix\": \"" + urlPrefix + "\", /* 图片访问路径前缀 */\n" +
" \"catcherMaxSize\": 2048000, /* 上传大小限制,单位B */\n" +
" \"catcherAllowFiles\": [\".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\"], /* 抓取图片格式显示 */\n" +
"\n" +
" /* 上传视频配置 */\n" +
" \"videoActionName\": \"uploadvideo\", /* 执行上传视频的action名称 */\n" +
" \"videoFieldName\": \"upfile\", /* 提交的视频表单名称 */\n" +
" \"videoPathFormat\": \"/ueditor/video/{yyyy}{mm}{dd}/\", /* 上传保存路径,可以自定义保存路径和文件名格式 */\n" +
" \"videoUrlPrefix\": \"\", /* 视频访问路径前缀 */\n" +
" \"videoMaxSize\": 10240000, /* 上传大小限制,单位B,默认10MB */\n" +
" \"videoAllowFiles\": [\n" +
" \".flv\", \".swf\", \".mkv\", \".avi\", \".rm\", \".rmvb\", \".mpeg\", \".mpg\",\n" +
" \".ogg\", \".ogv\", \".mov\", \".wmv\", \".mp4\", \".webm\", \".mp3\", \".wav\", \".mid\"], /* 上传视频格式显示 */\n" +
" /* 上传文件配置 */\n" +
" \"fileActionName\": \"uploadfile\", /* controller里,执行上传视频的action名称 */\n" +
" \"fileFieldName\": \"upfile\", /* 提交的文件表单名称 */\n" +
" \"filePathFormat\": \"/ueditor/file/{yyyy}{mm}{dd}/\", /* 上传保存路径,可以自定义保存路径和文件名格式 */\n" +
" \"fileUrlPrefix\": \"\", /* 文件访问路径前缀 */\n" +
" \"fileMaxSize\": 10240000, /* 上传大小限制,单位B,默认10MB */\n" +
" \"fileAllowFiles\": [\n" +
" \".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\",\n" +
" \".flv\", \".swf\", \".mkv\", \".avi\", \".rm\", \".rmvb\", \".mpeg\", \".mpg\",\n" +
" \".ogg\", \".ogv\", \".mov\", \".wmv\", \".mp4\", \".webm\", \".mp3\", \".wav\", \".mid\",\n" +
" \".rar\", \".zip\", \".tar\", \".gz\", \".7z\", \".bz2\", \".cab\", \".iso\",\n" +
" \".doc\", \".docx\", \".xls\", \".xlsx\", \".ppt\", \".pptx\", \".pdf\", \".txt\", \".md\", \".xml\"\n" +
" ], /* 上传文件格式显示 */\n" +
" /* 列出指定目录下的图片 */\n" +
" \"imageManagerActionName\": \"listimage\", /* 执行图片管理的action名称 */\n" +
" \"imageManagerListPath\": \"/ueditor/image/{yyyy}{mm}{dd}/\", /* 指定要列出图片的目录 */\n" +
" \"imageManagerListSize\": 20, /* 每次列出文件数量 */\n" +
" \"imageManagerUrlPrefix\": \"" + urlPrefix + "\", /* 图片访问路径前缀 */\n" +
" \"imageManagerInsertAlign\": \"none\", /* 插入的图片浮动方式 */\n" +
" \"imageManagerAllowFiles\": [\".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\"], /* 列出的文件类型 */\n" +
" /* 列出指定目录下的文件 */\n" +
" \"fileManagerActionName\": \"listfile\", /* 执行文件管理的action名称 */\n" +
" \"fileManagerListPath\": \"/ueditor/file/{yyyy}{mm}{dd}/\", /* 指定要列出文件的目录 */\n" +
" \"fileManagerUrlPrefix\": \"\", /* 文件访问路径前缀 */\n" +
" \"fileManagerListSize\": 20, /* 每次列出文件数量 */\n" +
" \"fileManagerAllowFiles\": [\n" +
" \".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\",\n" +
" \".flv\", \".swf\", \".mkv\", \".avi\", \".rm\", \".rmvb\", \".mpeg\", \".mpg\",\n" +
" \".ogg\", \".ogv\", \".mov\", \".wmv\", \".mp4\", \".webm\", \".mp3\", \".wav\", \".mid\",\n" +
" \".rar\", \".zip\", \".tar\", \".gz\", \".7z\", \".bz2\", \".cab\", \".iso\",\n" +
" \".doc\", \".docx\", \".xls\", \".xlsx\", \".ppt\", \".pptx\", \".pdf\", \".txt\", \".md\", \".xml\"\n" +
" ] /* 列出的文件类型 */\n" +
"}";
PrintWriter writer=response.getWriter();
writer.write(exec);
writer.flush();
writer.close();
}
```
3.前端导入文件
代码如下:
methods: {
ready(editorInstance) {
this.editorInstance=editorInstance
async uploadWordFile(event) {
const file=event.target.files[0];
if (!file) return;
// 将Word文件转换为HTML
const htmlContent=await this.convertWordToHtml(file);
const jsonData=JSON.parse(htmlContent)
// 设置UEditor的内容
console.log(jsonData)
this.editorInstance.execCommand('inserthtml',jsonData.data)
},
async convertWordToHtml(wordFile) {
// 这里应该是Word文件转HTML的后端接口调用代码
// 假设有一个转换Word为HTML的后端API
const formData=new FormData();
formData.append('file', wordFile);
const response=await fetch('/api/ue/uploadFile',{
method:'POST',
body:formData
})
if (response.ok) {
return await response.text();
}
throw new Error('转换失败');
}
}
4.后端读取文件生成html
代码如下:
/** word文档上传
*
* @param file
* @return
*/
@PostMapping("/uploadFile")
public Object uploadFile(@RequestParam(name="file") MultipartFile file){
String filename=file.getOriginalFilename();
JSONObject result=new JSONObject();
String visitHtml="";
try {
if (filename.endsWith(".docx")) {
//TODO 处理docx格式的
visitHtml=WordConverHtmlUtils.docxToHtmlText(file, ueProperties);
} else if (filename.endsWith(".doc")) {
//TODO 处理doc格式的
visitHtml=WordConverHtmlUtils.docToHtmlText(file, ueProperties);
} else {
log.error("不支持的文件格式!");
}
result.put("state", "SUCCESS");
result.put("data", visitHtml);
log.info("result: {}", result.toString());
} catch (Exception e) {
log.error("文件找不到异常!");
e.printStackTrace();
}
return result;
}
5.WordConverHtmlUtils工具类
??????????
options.URIResolver(new BasicURIResolver(picUri));
picUri地址,必须能通过浏览器直接访问,否则编辑器中无法渲染出来图片; 比如作者:http://localhost:8000/resource/ueditor/file/20240404/1712220732312.png(本地搭建NG测试)
??????????
代码如下:
package com.ue.demo.utils;
import cn.hutool.core.lang.UUID;
import com.ue.demo.config.UeProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.PicturesManager;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.apache.poi.xwpf.converter.core.BasicURIResolver;
import org.apache.poi.xwpf.converter.core.FileImageExtractor;
import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter;
import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.web.multipart.MultipartFile;
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* @author:Peanut
* @create: 2024-04-05 10:22
* @version: 1.0.0
* @description:
*/
@Slf4j
public class WordConverHtmlUtils {
private final static String FILE_URL_PRE="/ueditor/file/";
/**
* 上传docx文档,返回解析后的Html
*/
public static String docxToHtmlText(MultipartFile file, UeProperties ueProperties) throws Exception {
try {
String fileName=UUID.fastUUID().toString();
//图片存放地址
String imagePath=ueProperties.getSavepath().concat(FILE_URL_PRE).concat("/");
String fileOutName=imagePath.concat(fileName).concat(".html");
log.info("上传docx文档解析");
log.info("上传docx文档,返回解析后的Html, imagePath:{}", imagePath);
log.info("fileOutName:{}", fileOutName);
//获取一个用操作Word的对象
XWPFDocument document=new XWPFDocument(file.getInputStream());
//导出为html时的一些基本设置类
XHTMLOptions options=null;
//判断word文件中是否有图片
if(document.getAllPictures().size() > 0) {
//获取默认的对象,设置缩进indent
options=XHTMLOptions.getDefault().indent(4);
// 如果包含图片的话,要设置图片的导出位置
File imageFolder=new File(imagePath);
//设置图片抽取器的目的地文件夹 用于存放图片文件
options.setExtractor(new FileImageExtractor(imageFolder));
// URI resolver word的html中图片的目录路径
//??????????????????????????????????
//?????????? 这里需要设置为前端能过直接访问到的图片地址, 比如作者:http://localhost:8000/resource/ueditor/file/20240404/1712220732312.png,
//?????????? 否则,ueditor编辑器无法显示word文档中的图片
String picUri=ueProperties.getShowpath().concat(imagePath.substring(imagePath.indexOf("ueditor")));
options.URIResolver(new BasicURIResolver(picUri));
}
//获取输出的html文件对象
File outFile=new File(fileOutName);
if(!outFile.getParentFile().exists()){
outFile.getParentFile().mkdirs();
}
//创建所有的父路径,如果不存在父目录的话
outFile.getParentFile().mkdirs();
//创建一个输出流
OutputStream out=new FileOutputStream(outFile);
//html转换器
XHTMLConverter.getInstance().convert(document, out, options);
log.info("html转换器 success");
//处理生成的html,字符串形式给前端
return readHtmlStr(fileOutName);
} catch (Exception e) {
log.error("docxToHtmlText 解析异常", e);
}
return "";
}
/**
* 上传doc格式Word文档,返回解析后的Html
* @param file
* @param ueProperties
* @return
* @throws Exception
*/
public static String docToHtmlText(MultipartFile file, UeProperties ueProperties) throws Exception {
//使用字符数组流获取解析的内容
ByteArrayOutputStream baos=new ByteArrayOutputStream();
OutputStream outStream=new BufferedOutputStream(baos);
try {
String fileName=UUID.fastUUID().toString();
//将上传的文件传入Document转换
//图片存放地址
String docPath=ueProperties.getSavepath().concat(FILE_URL_PRE).concat("/");
String imagePath=docPath.concat("image/");
String fileOutName=docPath.concat(fileName).concat(".html");
log.info("上传doc文档,返回解析 ");
log.info("fileOutName:{}", fileOutName);
//创建图片文件的存储目录
new File(imagePath).mkdirs();
//poi中doc文档对应的实体类
HWPFDocument hwpfDocument=new HWPFDocument(file.getInputStream());
//使用空的文档对象构建一个转换对象
WordToHtmlConverter converter=new WordToHtmlConverter(DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.newDocument());
//设置存储图片的管理者--使用匿名内部类实现 该类实现了PicturesManager接口,实现了其中的savePicture方法
converter.setPicturesManager(new PicturesManager() {
FileOutputStream out=null;
//在下面的processDocument方法内部会调用该方法 用于存储word中的图片文件
@Override
public String savePicture(byte[] bytes, PictureType pictureType, String name, float width, float height) {
try {
//单个照片的保存
out=new FileOutputStream(imagePath + name);
out.write(bytes);
} catch (IOException exception) {
exception.printStackTrace();
}finally {
if(out !=null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//这里要返回给操作者(HtmlDocumentFacade)一个存储的路径 用于生成Html时定位到图片资源
//??????????????????????????????????
//?????????? 这里需要设置为前端能过直接访问到的图片地址, 比如作者:http://localhost:8000/resource/ueditor/file/20240404/1712220732312.png,
//?????????? 否则,ueditor编辑器无法显示word文档中的图片
return ueProperties.getShowpath().concat(imagePath.substring(imagePath.indexOf("ueditor"))).concat(name);
}
});
//使用外观模式,将hwpfDocument文档对象设置给HtmlDocumentFacade中的Document属性
converter.processDocument(hwpfDocument);
//获取转换器中的document文档
Document htmlDocument=converter.getDocument();
//充当文档对象模型 (DOM) 树形式的转换源树的持有者 -- 源树
DOMSource domSource=new DOMSource(htmlDocument);
//转换器 该对象用于将源树转换为结果树
Transformer transformer=TransformerFactory.newInstance().newTransformer();
//设置输出时的以什么方式输出,也可说是结果树的文件类型 可以是html/xml/text或者是一些扩展前三者的扩展类型
transformer.setOutputProperty(OutputKeys.METHOD , "html");
//设置一些必要的属性 设置输出时候的编码为utf-8
transformer.setOutputProperty(OutputKeys.ENCODING , "utf-8");
//转换 将输入的源树转换为结果树并且输出到streamResult中
transformer.transform(domSource , new StreamResult(new File(fileOutName)));
log.info("html转换器 success");
//处理生成的html,字符串形式给前端
return readHtmlStr(fileOutName);
} catch (Exception e) {
log.error("docToHtmlText 异常", e);
} finally {
baos.close();
outStream.close();
}
return null;
}
/**
* 读取html文件,转成字符串返回给前端
* 去除换行,以及连续两个空格
* @param htmlDirPath html文件路径
* @return
* @throws IOException
*/
private static String readHtmlStr(String htmlDirPath) throws IOException {
log.info("处理生成的html,字符串形式给前端:{} ...Start..", htmlDirPath);
String htmlStr="";
try {
Path htmlPath=Paths.get(htmlDirPath);
htmlStr=new String(Files.readAllBytes(htmlPath));
htmlStr=htmlStr.replaceAll("\\n", "");
htmlStr=htmlStr.replaceAll("\\s{2,}", " ");
log.info("处理生成的html,字符串形式给前端。。。end");
} catch (IOException e) {
log.error("处理生成的html,字符串形式出错了, {}", e.getMessage());
}
return htmlStr;
}
}
6.后端配置文件
代码如下:
spring.application.name=ue
server.port=8000
##UE编辑器配置
#编辑器访问服务器的图片地址
ue.showpath=http://localhost:8000/resource
#ue文件存储路径前缀
ue.savepath=/Users/cookie/Documents/coding/uedemo
```
!!! ue.showpath=生产上有nginx需要在nginx.conf进行配置
三、实现效果
成功通过导入word文章,回显内容到ueditor编辑器
总结
*赠人玫瑰,手留余香*
源码地址:
https://gitee.com/gwancookie/uedemo
**读取word文档生成html借鉴:**
https://blog.csdn.net/qq_44717657/article/details/124497326
文本编辑器实现效果图:
关注,转发,私信小编“01”即可获取Python入门学习资料!
左侧编辑区域,右侧渲染到HTML显示效果,除了渲染时候代码样式有所不同,其他标题、文字、图片基本满足所见即所得的效果
下面讲解富文本编辑器在Django项目中如何使用
1、前端页面引入js文件:
所用编辑器为tinymce.js,引入两个js文件
2、html代码布局:
左侧编辑区域,右侧渲染后预览区域
下面div左浮动,里面的textarea是富文本编辑区域,注意id要用rich_content,name也要加, {{ content }}是我在提交时候后端返回的数据,方便重新在编辑区域渲染数据
submit通过表单默认的提交方式向后端发post请求传数据
下面是右侧展示的div,右浮动,左右浮动为了更好地对比效果,不用来回滑动滚动条,返回的content其实就是html字符串,我们渲染到浏览器即可
3、Django后端代码
@csrf_exempt是ajax和form表单的post请求csrf解决办法,如果是form表单的post请求,也可以在form中加{% csrf_token %}
前端是form表单请求,后端只需要根据键从表单中读数据就行,我们的富文本编辑器name属性值为content,则直接get("content")即可
返回到前端的content,即富文本的html字符串,我们分别在编辑器和右侧都进行了渲染,即可见到最开始的效果
本文富文本编辑器仅测试部分常见效果没有什么问题,另外富文本编辑器也有CKeditor、Ueditor等等,如果大佬们有关于这些的开源demo,也欢迎学习交流
*请认真填写需求信息,我们会在24小时内与您取得联系。