一.UEditor涂鸦功能

UEditor的涂鸦功能的实现原理是运用H5的标签(该标签用于在网页上绘制图形)供用户在浏览器上绘制2D图型,并通过JS的Base64加密后用Ajax异步提交至后台再经过Base64解密成betye字节数组再转化为输入流存储在服务器上的过程。

js 移动端html5富文本编辑器 web富文本编辑器实现_上传

UEditor 涂鸦功能展示-用户进行涂鸦

js 移动端html5富文本编辑器 web富文本编辑器实现_js 移动端html5富文本编辑器_02

UEditor涂鸦功能展示-回显在页面上

2.2动手整合ueditor涂鸦功能

2.2.1 关于ueditor.config.js

打开涂鸦按钮

找到 toolbar的定义处,并确保涂鸦按钮是开放状态,如下图所示

js 移动端html5富文本编辑器 web富文本编辑器实现_上传_03

定义好涂鸦后台地址

然后在本文件中定义好涂鸦的后台访问地址,如下图所示

js 移动端html5富文本编辑器 web富文本编辑器实现_System_04

2.2.2 关于scrawl.js

本文件涉及到涂鸦前端如何将图片提交到后台,以及前端如何回显等问题

后台方法入口

js 移动端html5富文本编辑器 web富文本编辑器实现_System_05

原代码664行

将原代码getActionUrl注释掉,并添加以下代码,重新定义后台服务入口及参数

varcontextRootPath = editor.getOpt(‘contextRootPath’);

var actionUrl =contextRootPath+editor.getOpt(‘scrawlActionName’),

params =‘filetype=scrawl’;

js 移动端html5富文本编辑器 web富文本编辑器实现_System_06


浏览器控制台打印输出涂鸦图片的后台地址前端图片回显

js 移动端html5富文本编辑器 web富文本编辑器实现_上传_07

原代码642行

重新定义了涂鸦图片回显链接

浏览器控制台打印输出涂鸦图片的回显链接地址

2.2.2 后台代码实施涂鸦图片服务端存储
后台服务

/**
	 * 涂鸦上传
	 * @param response
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping(value="/scrawlUpload",method = RequestMethod.POST)
	public Map<String, Object> scrawlUpload(HttpServletResponse response,  
            HttpServletRequest request)throws Exception{
		Map<String, Object> params = new HashMap<String, Object>();
		String filetype = request.getParameter("filetype");
		System.out.println("filetype:"+filetype);
		String upfile = request.getParameter("upfile");//Base64编码过的图片数据信息,对字节数组字符串进行Base64解码 
		System.out.println("upfile:"+upfile);
		String basePath = "";
		 if("scrawl".equals(filetype)){
			 basePath = LoadPropertiesDataUtils.getValue("lixy.uploading.url.scrawl");
		 }
		 if(basePath == null || "".equals(basePath)){
			 basePath = "d:/lixy/static";  //与properties文件中lyz.uploading.url相同,未读取到文件数据时为basePath赋默认值
		 }
		String fileName = String.valueOf(System.currentTimeMillis()).concat("_").concat(RandomUtils.getRandom(6)).concat(".").concat("png");
		StringBuilder sb = new StringBuilder();
		 //拼接保存路径
		sb.append(basePath).append("/").append(fileName);
		// 在自己的项目中构造出一个用于存放用户照片的文件夹
		File f = new File(sb.toString());
		if (!f.exists()) {
			f.getParentFile().mkdirs();
		}
		// 使用BASE64对图片文件数据进行解码操作
		BASE64Decoder decoder = new BASE64Decoder();
		try {
			// 通过Base64解密,将图片数据解密成字节数组
			byte[] bytes = decoder.decodeBuffer(upfile);
			// 构造字节数组输入流
			ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
			// 读取输入流的数据
			BufferedImage bi = ImageIO.read(bais);
			// 将数据信息写进图片文件中
			ImageIO.write(bi, "png", f);// 不管输出什么格式图片,此处不需改动
			 params.put("state", "SUCCESS");
			 params.put("url", sb.toString());
			 params.put("size", upfile.length());
			 params.put("original", fileName);
			 params.put("type", "png");
			bais.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	      
		return params;
	}

以上方法实现了涂鸦图片上传至后台后完成Base64解码并存储至服务器指定位置的功能

applications.properties配置服务端涂鸦图片存储路径

js 移动端html5富文本编辑器 web富文本编辑器实现_上传_08

涂鸦图片后台存储路径设置

js 移动端html5富文本编辑器 web富文本编辑器实现_js 移动端html5富文本编辑器_09


涂鸦生成图片存储在服务器指定目标

至于图片读取方法viewImagesToPage在上篇文章里有解释,这里就不重复了

三、UEditor视频功能

3.1 关于纠正上篇博文附件上传部分的纰漏

关于上一篇博文附件上传部分的代码有纰漏,如果不用到视频上传的功能,该纰漏可以被隐藏掉,但如果读者需要使用Ueditor的视频上传及播放功能,那么这个纰漏则必须修复。

上篇博文在谈到文件上传路径时提到webuploader.js 6199行

js 移动端html5富文本编辑器 web富文本编辑器实现_js 移动端html5富文本编辑器_10

其实webuploader.js作为整个web端文件上传的入口,文件类型filetype=file写死在这里是不合适的(关键原因是视频上传功能也要用到这段代码)。

正确的处理方式应该是以下代码(参考)

js 移动端html5富文本编辑器 web富文本编辑器实现_System_11

那么对应的文件上传attachment.js也由以下

js 移动端html5富文本编辑器 web富文本编辑器实现_上传_12

改为以下即可 actionUrl = actionUrl+’?filetype=file’

js 移动端html5富文本编辑器 web富文本编辑器实现_js 移动端html5富文本编辑器_13

3.2 关于webuploader.js

关于webuploader.js 6199行部分代码应该按3.1节介绍的那样进行调整去掉参数filetype=file,如不然,会影响到视频上传的业务逻辑。

3.3 关于ueditor.config.js

该文件是ueditor最重要的配置文件,后台配置基本定义在此。

js 移动端html5富文本编辑器 web富文本编辑器实现_上传_14

这里定义了videoActionName,videoFieldName,videoUrlPrefix,videoMaxSize,videoAllowFiles等视频上传必须用到的参数设置

videoActionName:

定义了视频上传后台类及方法 比如 /resource/upload/images (参考UploadImageController)

videoUrlPrefix:

视频访问路径 比如 /ueditor/resource/upload/fileDownLoad.do?(参考UploadImageController)

3.4 关于video.js

l 视频提交后台路径

原码第376行,建议不用getActionUrl获得actionUrl

js 移动端html5富文本编辑器 web富文本编辑器实现_上传_15


采用 actinotallow= editor.getOpt(‘videoActionName’) 直接获得ueditor.config.js中定义好的videoActionName

在actionUrl末尾追加”?filetype=video”做为参数传至后台

l 视频前端播放路径

原码第294行 url:uploadDir + file.url,建议改为

url: uploadDir + file.url+’&filename=’+file.original,

其中uploadDir来自先前在ueditor.config.js中定义好的videoUrlPrefix

js 移动端html5富文本编辑器 web富文本编辑器实现_js 移动端html5富文本编辑器_16


视频前端播放路径定义

js 移动端html5富文本编辑器 web富文本编辑器实现_System_17

浏览器控制台输出

3.5 视频上传控制类UploadImageController

本类是实现视频上传至服务指定目录的指定服务类,同时也是视频文件实现在线播放的服务类,与配置文件ueditor.config.js中定义的以下参数有关联

videoActionName:

定义了视频上传后台类及方法 比如 /resource/upload/images

videoUrlPrefix:

视频文件在线播放后台方法 比如 /ueditor/resource/upload/fileDownLoad.do?

代码参考如下

视频文件上传及存储方法images

/**
	 * 上传图片
	 * @param file
	 * @param request
	 * @param response
	 * @return MultipartFile uploadFile,
	 */
	@ResponseBody
	@RequestMapping(value="/images",method = RequestMethod.POST)
	public Map<String, Object> images (@RequestParam(value = "file", required = false) MultipartFile file, HttpServletRequest request, HttpServletResponse response){
		Map<String, Object> params = new HashMap<String, Object>();
		if (file == null){
            System.out.println("未获得上传文件!");			
			return null;
		}  
		try{
			 String filetype = request.getParameter("filetype")+"";
			 System.out.println("filetype:"+filetype);
			 String basePath = "";
			 if("image".equals(filetype)){
				 basePath = LoadPropertiesDataUtils.getValue("lixy.uploading.url.image");
			 }else if("file".equals(filetype)){
				 basePath = LoadPropertiesDataUtils.getValue("lixy.uploading.url.file");
			 }else if("video".equals(filetype)){
				 basePath = LoadPropertiesDataUtils.getValue("lixy.uploading.url.video");
			 }
			 if(basePath == null || "".equals(basePath)){
				 basePath = "d:/lixy/static";  //与properties文件中lyz.uploading.url相同,未读取到文件数据时为basePath赋默认值
			 }
			 System.out.println("filename:"+file.getOriginalFilename());
			 String ext = StringUtils.getExt(file.getOriginalFilename());
			 String fileName = String.valueOf(System.currentTimeMillis()).concat("_").concat(RandomUtils.getRandom(6)).concat(".").concat(ext);
			 StringBuilder sb = new StringBuilder();
			 //拼接保存路径
			 sb.append(basePath).append("/").append(fileName);
			 
			 String visitUrl = basePath.concat("/"+fileName);
			 File f = new File(sb.toString());
			 if(!f.exists()){
				 f.getParentFile().mkdirs();
			 }
			 OutputStream out = new FileOutputStream(f);
			 FileCopyUtils.copy(file.getInputStream(), out);
			 params.put("state", "SUCCESS");
			 params.put("url", visitUrl);
			 params.put("size", file.getSize());
			 params.put("original", fileName);
			 params.put("type", file.getContentType());
			 params.put("filename", file.getOriginalFilename());
			 System.out.println("url:"+visitUrl+" original:"+fileName+" filename:"+file.getOriginalFilename()+" type:"+file.getContentType());
		} catch (Exception e){
			 params.put("state", "ERROR");
			 e.printStackTrace();
		}
		 return params;
	}

视频文件在线播放方法fileDownLoad

/**
	 * 下载文件
	 * @param request
	 * @param response
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/fileDownLoad",method = RequestMethod.GET)
	public void fileDownLoad(HttpServletRequest request, HttpServletResponse response) throws IOException {
		// 下载本地文件
		String url = request.getParameter("url")+"";
		String fileName = request.getParameter("filename")+"";
		//如果是IE浏览器,则用URLEncode解析
		if(isMSBrowser(request)){
			fileName = URLEncoder.encode(fileName, "UTF-8");
		}else{//如果是谷歌、火狐则解析为ISO-8859-1
			fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
		}
		System.out.println("filename:"+fileName+" url:"+url);
		// 读到流中
		InputStream inStream = new FileInputStream(url);// 文件的存放路径
//		fileName = url.substring(url.lastIndexOf("/")+1);
//		System.out.println("filename:"+fileName);
		// 设置输出的格式
		response.reset();
//		response.setContentType("bin");
		response.setContentType("application/vnd.ms-excel;charset=utf-8");
		response.addHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
		// 循环取出流中的数据
		byte[] b = new byte[100];
		int len;
		try {
			while ((len = inStream.read(b)) > 0)
				response.getOutputStream().write(b, 0, len);
			inStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

细心的读者可能已经看出来了,这不就是下载文件的方法吗?没错,就是这样的,在线视频播放后台支撑方法就是普通文件下载方法,( 因为本质是从后台读取文件字节流)

3.6 关于视频上传服务器存储路径的问题

对视频文件的存储路径定义在applications.properties文件中

js 移动端html5富文本编辑器 web富文本编辑器实现_ide_18

后台的UploadImageController将对请求参数的不同将图片和附件存放在不同的目录中

js 移动端html5富文本编辑器 web富文本编辑器实现_System_19

js 移动端html5富文本编辑器 web富文本编辑器实现_js 移动端html5富文本编辑器_20

3.7 关于ueditor.all.js

原码17772行,将image改为video

js 移动端html5富文本编辑器 web富文本编辑器实现_ide_21

四、UEditor 音频功能

4.1 请参照第三章节介绍的视频功能

由于Ueditor默认的音频功能是去网上搜索音乐,这里介绍意义不大,由于第3章节已经完整介绍了Ueditor本地视频上传及在线播放的功能,同理音频文件也是可以按视频文件处理的,唯一不同的地方是,在线播放时没有图像(它是音频嘛)目前能支持的视、音频文件格式有

“.flv”, “.swf”,".mkv", “.avi”, “.rm”, “.rmvb”,".mpeg", “.mpg”,

“.ogg”, “.ogv”,".mov", “.wmv”, “.mp4”, “.webm”,".mp3", “.wav”, “.mid”

js 移动端html5富文本编辑器 web富文本编辑器实现_System_22


Ueditor默认支持的音频插件

js 移动端html5富文本编辑器 web富文本编辑器实现_上传_23

使用整合后的视频插件实现音频文件上传及在线播放

js 移动端html5富文本编辑器 web富文本编辑器实现_js 移动端html5富文本编辑器_24

上传成功后,点击播放按钮即开始在线播放音乐

五、案例分享

本文提供的完全与文章内容一致的案例,可供读者实际在本地运行

5.1 案例下载地址


5.2 运行准备工作

请参考上一篇博文

5.3 运行效果展示

js 移动端html5富文本编辑器 web富文本编辑器实现_上传_25

在线视频加涂鸦

js 移动端html5富文本编辑器 web富文本编辑器实现_System_26

视频在线播放

涂鸦按钮和视频上传按钮如下图左侧和右侧

js 移动端html5富文本编辑器 web富文本编辑器实现_js 移动端html5富文本编辑器_27