1. 程式人生 > >UEditor富文字編輯器整合經驗分享(二)

UEditor富文字編輯器整合經驗分享(二)

一、引言     

       12月23日在部落格上給大家分享了一篇《 UEditor富文字編輯器整合經驗分享(整合至SpringMVC)》文章(http://blog.csdn.net/lixinyao5281/article/details/78878774),主要內容是介紹了一下UEditor整合及使用,解決了圖片上傳、圖片回顯、檔案上傳、檔案下載等大家常關心的富文字應用的問題,至於擴充套件問題,比如 塗鴉、視訊、音訊播放這些更高階的內容並未涉及,今天本文主要來探討一下這幾個高階一些的UEditor功能的整合使用,及前後臺程式碼的關鍵點。本文解決的主要問題是UEditor塗鴉後生成圖片上傳、儲存、頁面顯示和視訊、音訊檔案(如mp4,mp3等)上傳、儲存、頁面線上播放的功能。


塗鴉生成圖片上傳並回顯


上傳視訊檔案並在線播放


二、UEditor塗鴉功能

2.1 ueditor塗鴉功能介紹

    UEditor的塗鴉功能的實現原理是運用H5的<canvas>標籤(該標籤用於在網頁上繪製圖形)供使用者在瀏覽器上繪製2D圖型,並通過JS的Base64加密後用Ajax非同步提交至後臺再經過Base64解密成betye位元組陣列再轉化為輸入流儲存在伺服器上的過程。



UEditor 塗鴉功能展示-使用者進行塗鴉

 

UEditor塗鴉功能展示-回顯在頁面上



2.2動手整合ueditor塗鴉功能

 

2.2.1 關於ueditor.config.js

開啟塗鴉按鈕

找到 toolbar的定義處,並確保塗鴉按鈕是開放狀態,如下圖所示


定義好塗鴉後臺地址

然後在本檔案中定義好塗鴉的後臺訪問地址,如下圖所示


2.2.2 關於scrawl.js

本檔案涉及到塗鴉前端如何將圖片提交到後臺,以及前端如何回顯等問題

後臺方法入口 


原始碼664行

將原始碼getActionUrl註釋掉,並新增以下程式碼,重新定義後臺服務入口及引數

varcontextRootPath = editor.getOpt('contextRootPath');

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

params ='filetype=scrawl';


瀏覽器控制檯列印輸出塗鴉圖片的後臺地址

前端圖片回顯


原始碼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配置服務端塗鴉圖片儲存路徑



塗鴉圖片後臺儲存路徑設定


塗鴉生成圖片儲存在伺服器指定目標 

至於圖片讀取方法viewImagesToPage在上篇文章裡有解釋,這裡就不重複了

三、UEditor視訊功能

3.1 關於糾正上篇博文附件上傳部分的紕漏


     關於上一篇博文附件上傳部分的程式碼有紕漏,如果不用到視訊上傳的功能,該紕漏可以被隱藏掉,但如果讀者需要使用Ueditor的視訊上傳及播放功能,那麼這個紕漏則必須修復。

上篇博文在談到檔案上傳路徑時提到webuploader.js 6199行


其實webuploader.js作為整個web端檔案上傳的入口,檔案型別filetype=file寫死在這裡是不合適的(關鍵原因是視訊上傳功能也要用到這段程式碼)。

正確的處理方式應該是以下程式碼(參考)


那麼對應的檔案上傳attachment.js也由以下


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


3.2  關於webuploader.js

      關於webuploader.js 6199行部分程式碼應該按3.1節介紹的那樣進行調整去掉引數filetype=file,如不然,會影響到視訊上傳的業務邏輯。

3.3 關於ueditor.config.js

    該檔案是ueditor最重要的配置檔案,後臺配置基本定義在此。


這裡定義了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 

採用 actionUrl= 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


視訊前端播放路徑定義


瀏覽器控制檯輸出

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檔案中


 後臺的UploadImageController將對請求引數的不同將圖片和附件存放在不同的目錄中



3.7 關於ueditor.all.js

 原碼17772行,將image改為video



四、UEditor 音訊功能

4.1  請參照第三章節介紹的視訊功能

     由於Ueditor預設的音訊功能是去網上搜索音樂,這裡介紹意義不大,由於第3章節已經完整介紹了Ueditor本地視訊上傳及線上播放的功能,同理音訊檔案也是可以按視訊檔案處理的,唯一不同的地方是,線上播放時沒有影象(它是音訊嘛)目前能支援的視、音訊檔案格式有

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

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


Ueditor預設支援的音訊外掛


使用整合後的視訊外掛實現音訊檔案上傳及線上播放


上傳成功後,點選播放按鈕即開始線上播放音樂

五、案例分享

    本文提供的完全與文章內容一致的案例,可供讀者實際在本地執行

5.1  案例下載地址

5.2 執行準備工作

       請參考上一篇博文

5.3 執行效果展示


線上視訊加塗鴉


視訊線上播放


塗鴉按鈕和視訊上傳按鈕如下圖左側和右側