Tinymce富文本添加word导入的支持
在前端使用导入Word文档并自动解析成html再插入到tinymce编辑器中,可以使用mammoth.js识别Word内容转换为Html并set到编辑器中,使用mammoth只可解析.docx格式的Word,目前的mammoth不支持.doc格式,后续升级也许会加上解析doc的功能。
mammoth.js转换word为html丢失了好多样式,因此不推荐使用,建议统一交由后端转换
如果使用了是Tinymce5,建议直接使用https://github.com/tinymce-plugin/tinymce-plugin 这个插件,效果也不错,但是只支持docx,官方示例地址:https://tinymce-plugin.gitee.io/packages/tp-importword/tpImporatwordDemo.html
为什么解析不了.doc
- .docx 格式的 Word 文档是一种基于 XML 和 ZIP 压缩技术的文件格式,其文件结构相对固定并且较为简单,可以通过一些开源的 JavaScript 库进行解析和转换。`
· - .doc 格式的 Word 文档是一种相对来说版本比较老一点并且是二进制格式的文件,文件结构比较复杂,具有较高的私有性和细节,需要专用微软 Office 应用程序才能完整读取。
Tinymce 支持调整
1.添加按钮
在init的setup中添加按钮
import mammoth from "mammoth";
import { ContentTypeEnum } from '@/api/types'
import http from '@/api'
......
// init中其余的配置[略]
setup: function (editor: any) {
editor.ui.registry.addIcon('importword','<svg t="1604625110140" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14669" width="24" height="24"><path d="M546.21184 76.9024a30.72 30.72 0 0 1 21.70368 8.9856l248.22784 247.75168a30.72 30.72 0 0 1 9.0112 21.74464v163.3792a10.24 10.24 0 0 1-10.24 10.24h-51.712a10.24 10.24 0 0 1-10.24-10.24v-109.568h-232.448a30.72 30.72 0 0 1-30.72-30.72v-229.888h-330.752v726.016h438.272a10.24 10.24 0 0 1 10.24 10.24v51.2a10.24 10.24 0 0 1-10.24 10.24h-478.72a30.72 30.72 0 0 1-30.72-30.72V107.6224a30.72 30.72 0 0 1 30.72-30.72h427.61728z m197.84192 531.712l-171.40736 141.43488a30.72 30.72 0 0 0 0 47.39072l171.40736 141.43488a10.24 10.24 0 0 0 14.2848-1.2288l36.01408-41.95328a10.24 10.24 0 0 0-1.6128-14.848l-94.68416-71.26016h232.43264a10.24 10.24 0 0 0 10.24-10.24v-51.2a10.24 10.24 0 0 0-10.24-10.24h-232.448l94.69952-71.26016a10.24 10.24 0 0 0 1.6128-14.848l-36.01408-41.95328a10.24 10.24 0 0 0-14.2848-1.2288z m-323.8912-224.512a10.24 10.24 0 0 1 10.24 10.24v51.2a10.24 10.24 0 0 1-10.24 10.24h-190.464a10.24 10.24 0 0 1-10.24-10.24v-51.2a10.24 10.24 0 0 1 10.24-10.24h190.464z m141.312-207.36v155.648a5.12 5.12 0 0 0 5.12 5.12h155.648l-160.768-160.768zM276.48 542.72l37.888 171.008 45.056-171.008h59.904l43.52 173.568 38.4-173.568h50.688l-60.928 248.832H437.76l-49.664-185.856-49.664 185.856H284.16L225.28 542.72h51.2z m143.68768-292.2496a10.24 10.24 0 0 1 10.24 10.24v51.2a10.24 10.24 0 0 1-10.24 10.24h-190.464a10.24 10.24 0 0 1-10.24-10.24v-51.2a10.24 10.24 0 0 1 10.24-10.24h190.464z" fill="#333"></path></svg>');
// 注册自定义按钮
editor.ui.registry.addButton("customImportwordBtn", {
// text: "上传Word",
icon: 'importword',
onAction: function () {
var input = document.createElement("input");
input.type = "file";
input.accept = ".doc,.docx";
// 执行上传文件操作
input.addEventListener("change", handleFileSelect, false);
// 获取上传文件base64数据
function arrayBufferToBase64(arrayBuffer: any) {
var binary = "";
var bytes = new Uint8Array(arrayBuffer);
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
function handleFileSelect(event) {
var file = event.target.files[0];
//获取上传文件后缀,如果是docx格式,则使用mammoth来进行解析,
//如果不是则访问后台,将文件传输流base64传递到后台
//生成文件,然后用java解析doc,并返回到前台
var extension = file.name.slice(
((file.name.lastIndexOf(".") - 1) >>> 0) + 2
);
if (extension === "docx") {
readFileInputEventAsArrayBuffer(event, function (arrayBuffer: any) {
var base64Data = arrayBufferToBase64(arrayBuffer);
console.log(base64Data);
mammoth
.convertToHtml({ arrayBuffer: arrayBuffer }, { ignoreEmptyParagraphs: false, })
.then(displayResult, function (error: any) {
console.error(error);
});
});
} else if (extension === "doc") {
let formData = new FormData()
formData.append('file', file)
http
.post<string>(`/WordToHtml`, formData, {
headers: { 'Content-Type': ContentTypeEnum.FORM_DATA },
})
.then((json: any) => {
tinymceInstance.activeEditor.setContent(json.Data);
})
.catch((err) => {
console.log(err);
})
// readFileInputEventAsArrayBuffer(event, function (arrayBuffer:any) {
// //base64文件流
// var base64Data = arrayBufferToBase64(arrayBuffer);
// var result = "后台请求";
// alert(result);
// console.log(base64Data);
// });
// //tinymce的set方法将内容添加到编辑器中
// tinymceInstance.activeEditor.setContent(result);
}
}
function displayResult(result) {
//tinymce的set方法将内容添加到编辑器中
tinymceInstance.activeEditor.setContent(result.value);
}
function readFileInputEventAsArrayBuffer(event, callback) {
var file = event.target.files[0];
var reader = new FileReader();
reader.onload = function (loadEvent) {
var arrayBuffer = loadEvent.target.result;
callback(arrayBuffer);
};
reader.readAsArrayBuffer(file);
}
// 触发点击事件,打开选择文件的对话框
input.click();
},
});
},
......
2.在按钮的栏目下显示新添加的按钮
toolbar: () => [
'print preview fullscreen | customImportwordBtn',
],
3.后端接口,使用.Net写的,分别尝试了Aspose和Spire,结果是Aspose的转换效果更好
public IActionResult WordToHtml(IFormFile file)
{
string fileName = file.FileName;
string fileExtension = fileName.Substring(fileName.LastIndexOf(".") + 1);
Document document = null;
if (fileExtension.Equals("doc"))
{
document = new Document(file.OpenReadStream(),new LoadOptions(){LoadFormat = LoadFormat.Doc});
}
else if (fileExtension.Equals("docx"))
{
document = new Document(file.OpenReadStream(),new LoadOptions(){LoadFormat = LoadFormat.Docx});
}
else
{
return new JsonResult(new
{
Msg = "不被支持的文档类型!"
});
}
HtmlSaveOptions options = new (SaveFormat.Html);
options.ExportImagesAsBase64 = true;
MemoryStream stream = new();
document.Save(stream, options);
stream.Position = 0;
StreamReader reader = new(stream);
string html = reader.ReadToEnd();
// Document document = new Document();
// if (fileExtension.Equals("doc"))
// {
// document.LoadFromStream(file.OpenReadStream(),FileFormat.Doc);
// }
// else if (fileExtension.Equals("docx"))
// {
// document.LoadFromStream(file.OpenReadStream(),FileFormat.Docx);
// }
// else
// {
// return new JsonResult(new
// {
// Msg = "不被支持的文档类型!"
// });
// }
// document.HtmlExportOptions.ImageEmbedded = true;
// document.HtmlExportOptions.IsExportDocumentStyles = true;
// document.HtmlExportOptions.HasHeadersFooters = true;
// MemoryStream stream = new();
// document.SaveToStream(stream, FileFormat.Html);
// stream.Position = 0;
//
// StreamReader reader = new(stream);
// string html = reader.ReadToEnd();
return new JsonResult(new
{
Data = html,
});
}
如果是.NET 6的项目并且需要部署在Linux上,可能需要新建一个运行时配置文件
runtimeconfig.template.json
,以启用Linux绘图的支持
{
"configProperties": {
"System.Drawing.EnableUnixSupport": true
}
}