wangEditor如何能实现直接粘贴把图片上传到服务器中?

1.4.2之后官方并没有做功能的改动,1.4.2在word复制这块没有bug,其他版本会出现手动无法转存的情况

本文使用的后台是Java。前端为Jsp(前端都一样,后台如果语言不通得自己做 Base64编码解码)

因为公司业务需要支持IE8 ,网上其实有很多富文本框,效果都很好。

例如www.wangEditor.com  但试了一圈都不支持IE8 。

所以回到Ueditor,由于官方没有维护,新的neuditor 也不知道什么时候能支持word自动转存,只能自己想办法。

如果没有必要,不建议使用ueditor。我也是没有办法。

改动过后的插件只适合IE8。

这里要说明的一点是百度官方的编辑器不支持word图片批量转存,粘贴word后需要手动选择图片再进行上传一次操作。网上找到的大部分的示例都是这个操作。如果需要自动批量上传word图片的话可以使用WordPaster这个控件。


1.IE设置

在受信任站点里添加信任网站。

这里本机测试使用的直接是   http://localhost

因为需要读取客户端的文件,所以需要设置允许访问数据源。

ActiveXObject设置可以去网上参考,这里不列举了。

前面的

到这里 IE 的准备工作完成了。

修改ueditor.all.js关键代码

14006行附近,如果是其他版本的ueditor,在功能正常的情况下,可以拷贝下面代码。

var imgPath = attrs.src;

var imgUrl = attrs.src;

if (navigator.appName === 'Microsoft Internet Explorer') { //判断是否是IE浏览器

 if (navigator.userAgent.match(/Trident/i) && navigator.userAgent.match(/MSIE 8.0/i)) { //判断浏览器内核是否为Trident内核IE8.0

var realPath = imgPath.substring(8, imgPath.length);

var filename = imgPath.substring(imgPath.lastIndexOf('/') + 1, imgPath.length);

var result = UploadForIE.saveAttachment(filename, realPath);

 if (result) {

var json = eval('(' + result + ')');

imgUrl = json.url;

 }

 }

}

img.setAttr({


width: attrs.width,

height: attrs.height,

alt: attrs.alt,

word_img: attrs.src,

src: imgUrl,

 'style': 'background:url(' + (flag ? opt.themePath + opt.theme + '/images/word.gif': opt.langPath + opt.lang + '/images/localimage.png') + ') no-repeat center center;border:1px solid #ddd'

})


uploadForIE.js。

var UploadForIE = {

 // 保存到xml附件,并且通过ajax 上传

saveAttachment: function(upload_filename, localFilePath) {

 //后台接受图片保存的方法。

var upload_target_url = "uploadImg";

var strTempFile = localFilePath;

 // 创建XML对象,组合XML文档数据

var xml_dom = UploadForIE.createDocument();

xml_dom.loadXML(' ');

 // 创建ADODB.Stream对象

var ado_stream = new ActiveXObject("adodb.stream");

 // 设置流数据类型为二进制类型

ado_stream.Type = 1; // adTypeBinary

 // 打开ADODB.Stream对象

ado_stream.Open();

 // 将本地文件装载到ADODB.Stream对象中

ado_stream.LoadFromFile(strTempFile);

 // 获取文件大小(以字节为单位)

var byte_size = ado_stream.Size;

 // 设置数据传输单元大小为1KB

var byte_unit = 1024;

 // 获取文件分割数据单元的数量

var read_count = parseInt((byte_size / byte_unit).toString()) + parseInt(((byte_size % byte_unit) == 0) ? 0 : 1);


 // 创建XML元素节点,保存上传文件名称

var node = xml_dom.createElement("uploadFilename");

node.text = upload_filename.toString();

var root = xml_dom.documentElement;

root.appendChild(node);


 // 创建XML元素节点,保存上传文件大小

var node = xml_dom.createElement("uploadFileSize");

node.text = byte_size.toString();

root.appendChild(node);


 // 创建XML元素节点,保存上传文件内容

 for (var i = 0; i < read_count; i++) {

var node = xml_dom.createElement("uploadContent");

 // 文件内容编码方式为Base64

node.dataType = "bin.base64";

 // 判断当前保存的数据节点大小,根据条件进行分类操作

 if ((parseInt(byte_size % byte_unit) != 0) && (i == parseInt(read_count - 1))) {

 // 当数据包大小不是数据单元的整数倍时,读取最后剩余的小于数据单元的所有数据

node.nodeTypedValue = ado_stream.Read();

 } else {

 // 读取一个完整数据单元的数据

node.nodeTypedValue = ado_stream.Read(byte_unit);

 }

root.appendChild(node);

 }


 // 关闭ADODB.Stream对象

ado_stream.Close();

delete ado_stream;

 // 创建Microsoft.XMLHTTP对象

 // var xmlhttp = new ActiveXObject("microsoft.xmlhttp");

var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHttp");

 // 打开Microsoft.XMLHTP对象

xmlhttp.open("post", upload_target_url, false);

 // 使用Microsoft.XMLHTP对象上传文件

xmlhttp.send(xml_dom);

var state = xmlhttp.readyState;

var success_state = true;

 if (state != 4) {

success_state = false;

 }

var result = xmlhttp.responseText;


delete xmlhttp;

 return result;

 },


 // 创建DOMdocuemnt

createDocument: function() {

var xmldom;

var versions = ["MSXML2.DOMDocument.6.0", "MSXML2.DOMDocument.5.0", "MSXML2.DOMDocument.4.0", "MSXML2.DOMDocument.3.0", "MSXML2.DOMDocument"],

i,

len;

 for (i = 0, len = versions.length; i < len; i++) {

 try {

xmldom = new ActiveXObject(versions[i]);

 if (xmldom != null) break;

 } catch(ex) {

 //跳过

alert("创建document对象失败!");

 }

 }

 return xmldom;

 }

}


UEditorAction保存图片方法

@RequestMapping("/uploadImg")

 public void uploadADO(HttpServletRequest request, HttpServletResponse response) {

String path1 = request.getContextPath();

String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() +path1;


String rootPath = request.getServletContext().getRealPath("/");

 // 设置数据传输单元大小为1KB

 int unit_size = 1024;

 // 初始化xml文件大小(以字节为单位)

 int xmlFileSize = 0;

 // 初始化上传文件名称(完整文件名)

String xmlFilename = "";

 // 初始化上传文件保存路径(绝对物理路径)

String xmlFilepath = "";

 // 声明文件存储字节数组

 byte[] xmlFileBytes = null;

 try {

 // 初始化 SAX 串行xml文件解析器

SAXBuilder builder = new SAXBuilder();

Document doc = builder.build(request.getInputStream());

Element eRoot = doc.getRootElement();

 // 获取上传文件的完整名称

Iterator it_name = eRoot.getChildren("uploadFilename").iterator();

 if (it_name.hasNext()) {

xmlFilename = ((Element) it_name.next()).getText();

 }

 //存放的相对路径目录

StringrelativePath = "/temp/"+EditorUtil.getToday()+"/";

xmlFilepath = rootPath+ relativePath;


 // 获取上传文件的大小

Iterator it_size = eRoot.getChildren("uploadFileSize").iterator();

 if (it_size.hasNext()) {

xmlFileSize = Integer.parseInt(((Element) it_size.next())

 .getText());

 if (xmlFileSize > 0) {

 int unit_count = 0;

 // 为存储文件内容的字节数组分配存储空间

xmlFileBytes = new byte[xmlFileSize];

 // 循环读取文件内容,并保存到字节数组中

Iterator it_content = eRoot.getChildren("uploadContent")

 .iterator();

 while (it_content.hasNext()) {

 // 初始化Base64编码解码器

BASE64Decoder base64 = new BASE64Decoder();

 byte[] xmlNodeByteArray = base64

 .decodeBuffer(((Element) it_content.next())

 .getText());

 if (xmlNodeByteArray.length >= unit_size) {

 // 读取一个完整数据单元的数据

System.arraycopy(xmlNodeByteArray, 0, xmlFileBytes,

unit_count * unit_size, unit_size);

 } else {

 // 读取小于一个数据单元的所有数据

System.arraycopy(xmlNodeByteArray, 0, xmlFileBytes,

unit_count * unit_size, xmlFileSize

 % unit_size);

 }

 // 继续向下读取文件内容

unit_count++;

 }

 }

 }


 // 保存路径

File path = new File(xmlFilepath);

 if(!path.exists()){

path.mkdirs();

 }

 // 保存文件 word粘贴图片的名称

File file = new File(path,xmlFilename);

 // 创建文件输入输出流

FileOutputStream fos = new FileOutputStream(file);

 // 写入文件内容

fos.write(xmlFileBytes);

fos.flush();

 // 关闭文件输入输出流

fos.close();


ReturnUploadImage rui = new ReturnUploadImage();

rui.setTitle(xmlFilename);//这里需要设置文件名称如:xxx.jpg

rui.setOriginal(xmlFilename);//这里需要设置文件名称如:xxx.jpg

rui.setState("SUCCESS");

rui.setUrl(basePath +relativePath+xmlFilename);


JSONObject json = new JSONObject(rui);

 String result = json.toString();//这边就是为了返回给UEditor做的格式转换

response.getWriter().write(result);

 } catch (Exception e) {

e.printStackTrace();

 }

 }

优化后的代码:

upload.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<%@ page contentType="text/html;charset=utf-8"%>

<%@ page import = "Xproer.*" %>

<%@ page import="org.apache.commons.lang.StringUtils" %>

<%@ page import="org.apache.commons.fileupload.*" %>

<%@ page import="org.apache.commons.fileupload.disk.*" %>

<%@ page import="org.apache.commons.fileupload.servlet.*" %>

<%out.clear();

/*

 更新记录:

2013-01-25 取消对SmartUpload的使用,改用commons-fileupload组件。因为测试发现SmartUpload有内存泄露的问题。

*/

//String path = request.getContextPath();

//String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";


String uname = "";// = request.getParameter("uid");

String upass = "";// = request.getParameter("fid");

// Check that we have a file upload request

boolean isMultipart = ServletFileUpload.isMultipartContent(request);

FileItemFactory factory = new DiskFileItemFactory();

ServletFileUpload upload = new ServletFileUpload(factory);

//upload.setSizeMax(262144);//256KB

List files = null;

try

{

files = upload.parseRequest(request);

}

catch (FileUploadException e)

{// 处理文件尺寸过大异常

out.println("上传文件异常:"+e.toString());

 return;

}


FileItem imgFile = null;

// 得到所有上传的文件

Iterator fileItr = files.iterator();

// 循环处理所有文件

while (fileItr.hasNext())

{

 // 得到当前文件

imgFile = (FileItem) fileItr.next();

 // 忽略简单form字段而不是上传域的文件域(等)

 if(imgFile.isFormField())

{

String fn = imgFile.getFieldName();

String fv = imgFile.getString();

 if(fn.equals("uname")) uname = fv;

 if(fn.equals("upass")) upass = fv;

}

 else

{

 break;

}

}

Uploader up = new Uploader(pageContext,request);

up.SaveFile(imgFile);

String url = up.GetFilePathRel();

out.write(url);

response.setHeader("Content-Length",url.length()+"");//返回Content-length标记,以便控件正确读取返回地址。

%>


剩下的后台功能和js参考下载文件中的UEditorAction 和 uploadForIE.js。

下面是我安装的依赖pom结构,可以根据自己的进行调整。

  <dependency>

            <groupId>com.baidu</groupId>

            <artifactId>ueditor</artifactId>

            <version>1.1.0</version>

        </dependency>


基于springboot 和idea ,这里只提取了自动转存功能出来,功能还没测试,git代码没做公开,等后续测试好了再公开。

可以先使用csdn下载查看代码。

pom里引用了ueditor.jar

需要根据各自情况安装jar包

1.4.2中的jar包版本是1.1.0

mvn install:install-file -DgroupId=com.baidu -DartifactId=ueditor -Dversion=1.1.0 -Dpackaging=jar -Dfile=\ueditor\jsp\lib\ueditor-1.1.0.jar

运行

UeditorApplication的main方法

然后访问http://localhost:8088/ueditor/ 就可以测试了。


完成后的效果:

图片自动批量上传,不需要手动一张张选择图片上传,用户体验比百度ueditor自带的更好,传图效率更高。


上传成功后,图片地址自动替换成服务器地址,图片自动保存在服务器中

详细资料可以参考这篇文章:

http://blog.ncmem.com/wordpress/2019/08/12/ueditor-word%E5%9B%BE%E7%89%87%E8%BD%AC%E5%AD%98%E4%BA%A4%E4%BA%92/


讨论群:223813913

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339