工做中會遇到不少須要使用富文本編輯器的地方,好比我如今發佈這篇文章離不開這個神器,並且如今網上編輯器太多了。記得以前,因爲工做須要本身封裝過一個編輯器的公共插件,是用ckeditor改版的,目的是要兼容公司全部項目,使用方便。廢話很少說,今天寫這篇文章,一是總結本身學習複習,二是關於FTP上傳官方資料太少,也便於他人少趟坑,我在這裏會說的很細很明白,但願親們之後不要中槍了!javascript
去官網下載後,咱們須要把下載的編輯器文件夾,摘一部分放到項目中,下載以後的目錄,以下圖(我這裏用的是jsp簡化版 1.2.2)css
我在外面新建了個插件目錄umeditor,以下圖:html
除了jsp文件夾,其他拷到項目靜態資源的目錄中,而後 咱們來分析jsp文件夾都有哪些東東?前端
這裏,我把那兩個jar包帶入到項目中,這裏我改了名字,方便導入,fileupload那個jar包項目以前就有。以下圖:java
接下來,就是頁面調用了,很簡單,首先將編輯器所須要的樣式和腳本文件引入:web
/**以上省略,這裏引入到頁面頭部**/ <link href="${ctx}/static/umeditor/themes/default/css/umeditor.css" type="text/css" rel="stylesheet"> <script type="text/javascript" charset="utf-8" src="${ctx}/static/umeditor/umeditor.config.js"></script> <script type="text/javascript" charset="utf-8" src="${ctx}/static/umeditor/umeditor.min.js"></script> <script type="text/javascript" src="${ctx}/static/umeditor/lang/zh-cn/zh-cn.js"></script> </head>
接下來,須要在頁面調用編輯器對象,官方用的是script標籤,我這裏用textarea來構造算法
<div class="controls"> <form:textarea id="content" htmlEscape="true" path="articleData.content" rows="4" maxlength="200" class="input-xxlarge"/> <script type="text/javascript"> //實例化編輯器 var um = UM.getEditor('content'); //注意ID的一致 um.setWidth(700); //設置編輯器寬度 </script> </div>
至此基本的工做已作完,上述相信大部分搞開發的同胞們,都沒問題吧!效果圖以下:spring
官方下載給的後臺處理文件除了必要的jar外有三個文件:apache
(1) Uploader.java 文件 json
該文件主封裝了一個文件上傳對象,包括上傳後須要返回的參數、狀態、URL,除此還有一個上傳的處理函數,固然只是普通的文件存儲,不符合咱們的需求,可是咱們能夠知道前端須要的一些返回值。
(2) imageUp.jsp 文件
上傳圖片默認配置後臺處理文件,主要調用Upload上傳類,完成上傳 並把上傳結果 以json字符串發往前臺,其中包括重要的state、url等參數
(3) getContent.jsp 文件 (和上傳不要緊,略過)
以上分析過官方給的簡單後臺處理邏輯,咱們不難知道實際上就是須要咱們提供一個上傳處理函數並返回包含必要參數的JSON串
那好,接下來咱們開始寫本身的後臺上傳處理函數了。
第一步 後臺控制器處理函數(重要程度:☆☆☆☆☆)
1 /** 2 * 編輯器上傳圖片 3 */ 4 @RequiresPermissions("cms:article:view") 5 @RequestMapping(value={"/upload"}) 6 @ResponseBody() 7 public String upload(HttpServletRequest request,HttpServletResponse response){ 8 9 //request.getParameter("path"); 10 String[] allowExtName = {".jpg",".png",".gif",".bmp",".jpeg"};//圖片格式限制 11 List<MultipartFile> multipartFiles = getFileSet(request, 1024 * 1024 * 10, allowExtName); //上傳的圖片大小能夠放到配置中讀取,這裏設置10M 12 Map<String,Object> map = new HashMap<String,Object>(); 13 try { 14 if(multipartFiles.size() > 0){ 15 MultipartFile file = multipartFiles.get(0); 16 InputStream is = file.getInputStream(); 17 String tempFileName = file.getOriginalFilename(); 18 if(is != null&&StringUtils.isNotBlank(tempFileName)){ 19 20 //生成文件名 21 String uuid = IdGen.uuid(); //生成的一個隨機字符串,用於圖片名 22 String fileName = uuid+tempFileName.substring(tempFileName.indexOf(".")); 23 //生成文件路徑 24 boolean ftpWaterRs=true; 25 FTPUtils ftpUtils = FTPUtils.getInstance(); 26 SimpleDateFormat sf = new SimpleDateFormat("yyyy/MM/"); 27 String ss = sf.format(new Date()); //以當前時間,生成存放目錄,格式/yyyy/MM 28 String storePath = ftpUtils.getSaveFilePath() + ss; //讀取配置的存儲目錄 好比 /upload/image/ 29 //圖片加水印 getResourceRootRealPath ; 若圖片大小小於logo大小則不加水印 30 if(file.getSize()>1200){ //這裏給圖片增長水印功能 31 String waterName= uuid + "_water"+tempFileName.substring(tempFileName.indexOf(".")); 32 //緩存文件類型轉換 33 CommonsMultipartFile cf= (CommonsMultipartFile)file; 34 DiskFileItem fi = (DiskFileItem)cf.getFileItem(); 35 File tempFile = fi.getStoreLocation(); 36 String waterTempPath = SpringContextHolder.getRootRealPath()+"/"+waterName; 37 String logoPath=SpringContextHolder.getRootRealPath()+"/static/images/shuiyin.png"; //水印圖片路徑 38 ImageUtils.markImageByIcon(logoPath, tempFile, waterTempPath, 45); //添加水印 39 File waterFile = new File(waterTempPath); 40 //上傳水印圖片 41 ftpWaterRs = ftpUtils.storeFile(storePath,waterName,new FileInputStream(waterFile)); 42 if(ftpWaterRs){ 43 FileUtils.deleteFile(waterTempPath); 44 is.close(); 45 map.clear(); 46 map.put("state","SUCCESS"); //注意:返回的參數state 成功必須是 SUCCESS,不然須要到image.js中改,失敗能夠自定義 47 //map.put("url",ftpUtils.getSiteName().trim()+storePath.trim() + waterName); 48 map.put("url",storePath.trim() + waterName);
//url 這裏有個坑,絕對完整地址圖片不會顯示
//我如今返回的是不包含域名的路徑 如 /upload/images/2016/08/03/a23ssds6s6d56ds656a6a5652636.jpg
//域名部分路徑也就是http://static.xx.com/ 須要到前端配置,具體是 在umeditor.config.js 配置參數 imagePath 所謂的圖片修正地址嘍 49 return JsonMapper.toJsonString(map); 50 } 51 } 52 53 //上傳源文件 54 boolean ftpFileRs = ftpUtils.storeFile(storePath, fileName, is); 55 is.close(); 56 if(ftpFileRs){ //這裏水印圖片上傳失敗 會採用原圖 57 map.clear(); 58 map.put("state","SUCCESS"); 59 map.put("url",storePath.trim() + fileName); 60 return JsonMapper.toJsonString(map); 61 } 62 } 63 } 64 else{ 65 map.clear(); 66 map.put("state","請檢查圖片格式或尺寸,圖片必須小於10M"); 67 return JsonMapper.toJsonString(map); 68 } 69 } catch (Exception e) { 70 e.printStackTrace(); 71 } 72 map.clear(); 73 map.put("state","上傳請求異常"); 74 return JsonMapper.toJsonString(map); 75 }
第二步 處理函數用到上傳圖片驗證函數包含大小和格式(重要程度:☆☆☆)
1 /** 2 * @descrption 根據HttpServletRequest對象獲取MultipartFile集合 3 * @author zp 4 * @param request 5 * @param maxLength 6 * 文件最大限制 7 * @param allowExtName 8 * 不容許上傳的文件擴展名 9 * @return MultipartFile集合 10 */ 11 public static List<MultipartFile> getFileSet(HttpServletRequest request, 12 long maxLength, String[] allowExtName) { 13 MultipartHttpServletRequest multipartRequest = null; 14 try { 15 multipartRequest = (MultipartHttpServletRequest) request; 16 } catch (Exception e) { 17 return new LinkedList<MultipartFile>(); 18 } 19 20 List<MultipartFile> files = new LinkedList<MultipartFile>(); 21 files = multipartRequest.getFiles("upfile"); //upfile 是編輯器默認的上傳圖片表單name,在文件umeditor.config.js 可自定義配置參數 imageFieldName 22 // 移除不符合條件的 23 for (int i = 0; i < files.size(); i++) { 24 if (!validateFile(files.get(i), maxLength, allowExtName)) { 25 files.remove(files.get(i)); 26 if (files.size() == 0) { 27 return files; 28 } 29 } 30 } 31 return files; 32 } 33 34 /** 35 * @descrption 驗證文件格式,這裏主要驗證後綴名 36 * @author zp 37 * @param file 38 * MultipartFile對象 39 * @param maxLength 40 * 文件最大限制 41 * @param allowExtName 42 * 不容許上傳的文件擴展名 43 * @return 文件格式是否合法 44 */ 45 private static boolean validateFile(MultipartFile file, long maxLength, 46 String[] allowExtName) { 47 if (file.getSize() < 0 || file.getSize() > maxLength) 48 return false; 49 String filename = file.getOriginalFilename(); 50 51 // 處理不選擇文件點擊上傳時,也會有MultipartFile對象,在此進行過濾 52 if (filename == "") { 53 return false; 54 } 55 String extName = filename.substring(filename.lastIndexOf(".")) 56 .toLowerCase(); 57 if (allowExtName == null || allowExtName.length == 0 58 || Arrays.binarySearch(allowExtName, extName) != -1) { 59 return true; 60 } else { 61 return false; 62 } 63 }
第三步 FTP上傳處理類,絕對福利..好多人想要哦 0.0(重要程度:☆☆☆☆)
1 package com.xx.utils; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.IOException; 6 import java.io.InputStream; 7 8 import org.apache.commons.net.ftp.FTPClient; 9 import org.apache.commons.net.ftp.FTPFile; 10 import org.apache.commons.net.ftp.FTPReply; 11 12 import com.xx.Global; 13 14 /** 15 * FTP服務器工具類 16 */ 17 public class FTPUtils { 18 19 private static FTPUtils ftpUtils; 20 private FTPClient ftpClient; 21 //private FTPFile ftpFile; 22 private String port; // 服務器端口 23 private String username; // 用戶登陸名 24 private String password; // 用戶登陸密碼 25 private String serverName; // 服務名 26 private int localPasv;//開啓本地被動模式 27 private String siteName; // 站點域名 28 private String saveFilePath;//存儲路徑 29 30 31 private InputStream is; // 文件下載輸入流 32 33 /** 34 * 私有構造方法 35 */ 36 private FTPUtils() { 37 initConfig(); 38 if (null == ftpClient) { 39 ftpClient = new FTPClient(); 40 } 41 } 42 43 /** 44 * 獲取FTPUtils對象實例 45 * @return 46 * FTPUtils對象實例 47 */ 48 public synchronized static FTPUtils getInstance () { 49 if (null == ftpUtils) { 50 ftpUtils = new FTPUtils(); 51 } 52 return ftpUtils; 53 } 54 55 /** 56 * 初始化FTP服務器鏈接屬性 57 */ 58 // public void initConfig () { 59 // // 構造Properties對象 60 // Properties properties = new Properties(); 61 // 62 // // 定義配置文件輸入流 63 // InputStream is = null; 64 // try { 65 // // 獲取配置文件輸入流 66 // is = FTPUtils.class.getResourceAsStream("/ftp.properties"); 67 // // 加載配置文件 68 // properties.load(is); 69 // // 讀取配置文件 70 // port = (String) properties.get("port"); // 設置端口 71 // username = (String) properties.get("username1"); // 設置用戶名 72 // password = (String) properties.get("password1"); // 設置密碼 73 // serverName = (String) properties.get("serverName"); // 服務名 74 // localPasv = Integer.valueOf(String.valueOf(properties.get("localPasv"))); 75 // } catch (IOException e) { 76 // e.printStackTrace(); 77 // } finally { 78 // // 判斷輸入流是否爲空 79 // if (null != is) { 80 // try { 81 // // 關閉輸入流 82 // is.close(); 83 // } catch (IOException e) { 84 // e.printStackTrace(); 85 // } 86 // } 87 // } 88 // } 89 90 public void initConfig () { 91 serverName = Global.getConfig("ftp.serverName"); 92 // SystemConfig.getInstance().getApplication().get("ftp.serverName"); 93 port = Global.getConfig("ftp.port"); 94 // SystemConfig.getInstance().getApplication().get("ftp.port"); 95 username = Global.getConfig("ftp.username1"); 96 // SystemConfig.getInstance().getApplication().get("ftp.username1"); 97 password =Global.getConfig("ftp.password1"); 98 // portSystemConfig.getInstance().getApplication().get("ftp.password1"); 99 localPasv = Integer.valueOf(Global.getConfig("ftp.localPasv")); 100 // Integer.valueOf(SystemConfig.getInstance().getApplication().get("ftp.localPasv")); 101 siteName = Global.getConfig("ftp.readPath"); //讀取配置 訪問路徑 102 saveFilePath = Global.getConfig("ftp.upLoadPath"); //讀取配置 上傳路徑 103 104 } 105 /** 106 * 鏈接(配置通用鏈接屬性)至服務器 107 * 108 * @param serverName 109 * 服務器名稱 110 * @param remotePath 111 * 當前訪問目錄 112 * @return 113 * <b>true</b>:鏈接成功 114 * <br/> 115 * <b>false</b>:鏈接失敗 116 */ 117 public boolean connectToTheServer (String remotePath) { 118 // 定義返回值 119 boolean result = false; 120 try { 121 // 鏈接至服務器,端口默認爲21時,可直接經過URL鏈接 122 ftpClient.connect(serverName, Integer.parseInt(port)); 123 // 登陸服務器 124 ftpClient.login(username, password); 125 // 判斷返回碼是否合法 126 if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) { 127 // 不合法時斷開鏈接 128 ftpClient.disconnect(); 129 // 結束程序 130 return result; 131 } 132 if(localPasv==1) 133 ftpClient.enterLocalPassiveMode(); 134 // 設置文件操做目錄 135 result = createDirAndToDir(remotePath); 136 System.out.println("result===="+result); 137 // 設置文件類型,二進制 138 result = ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); 139 // 設置緩衝區大小 140 ftpClient.setBufferSize(3072); 141 // 設置字符編碼 142 ftpClient.setControlEncoding("UTF-8"); 143 } catch (IOException e) { 144 e.printStackTrace(); 145 } 146 return result; 147 } 148 149 /** 150 * 上傳文件至FTP服務器 151 * 152 * @param serverName 153 * 服務器名稱 154 * @param storePath 155 * 上傳文件存儲路徑 156 * @param fileName 157 * 上傳文件存儲名稱 158 * @param is 159 * 上傳文件輸入流 160 * @return 161 * <b>true</b>:上傳成功 162 * <br/> 163 * <b>false</b>:上傳失敗 164 */ 165 public boolean storeFile (String storePath, String fileName, InputStream is) { 166 boolean result = false; 167 try { 168 // 鏈接至服務器 169 result = connectToTheServer(storePath); 170 // 判斷服務器是否鏈接成功 171 if (result) { 172 // 上傳文件 173 result = ftpClient.storeFile(fileName, is); 174 } 175 // 關閉輸入流 176 is.close(); 177 } catch (IOException e) { 178 e.printStackTrace(); 179 } finally { 180 // 判斷輸入流是否存在 181 if (null != is) { 182 try { 183 // 關閉輸入流 184 is.close(); 185 } catch (IOException e) { 186 e.printStackTrace(); 187 } 188 } 189 // 登出服務器並斷開鏈接 190 ftpUtils.logout(); 191 } 192 return result; 193 } 194 195 /** 196 * 下載FTP服務器文件至本地<br/> 197 * 操做完成後需調用logout方法與服務器斷開鏈接 198 * 服務器名稱 199 * @param remotePath 200 * 下載文件存儲路徑 201 * @param fileName 202 * 下載文件存儲名稱 203 * @return 204 * <b>InputStream</b>:文件輸入流 205 */ 206 public InputStream retrieveFile (String remotePath, String fileName) { 207 try { 208 boolean result = false; 209 // 鏈接至服務器 210 result = connectToTheServer(remotePath); 211 // 判斷服務器是否鏈接成功 212 if (result) { 213 // 獲取文件輸入流 214 is = ftpClient.retrieveFileStream(fileName); 215 } 216 } catch (IOException e) { 217 e.printStackTrace(); 218 } 219 return is; 220 } 221 222 /** 223 * 刪除FTP服務器文件 224 * 225 * @param serverName 226 * 服務器名稱 227 * @param remotePath 228 * 當前訪問目錄 229 * @param fileName 230 * 文件存儲名稱 231 * @return 232 * <b>true</b>:刪除成功 233 * <br/> 234 * <b>false</b>:刪除失敗 235 */ 236 public boolean deleteFile (String serverName, String remotePath, String fileName) { 237 boolean result = false; 238 // 鏈接至服務器 239 result = connectToTheServer(remotePath); 240 // 判斷服務器是否鏈接成功 241 if (result) { 242 try { 243 // 刪除文件 244 result = ftpClient.deleteFile(fileName); 245 } catch (IOException e) { 246 e.printStackTrace(); 247 } finally { 248 // 登出服務器並斷開鏈接 249 ftpUtils.logout(); 250 } 251 } 252 return result; 253 } 254 255 /** 256 * 建立目錄 257 * 258 * @param remotePath 259 * 目錄儲路徑 260 * @return 261 * <b>true</b>:建立成功 262 * <br/> 263 * <b>false</b>:建立失敗 264 */ 265 public boolean createDirAndToDir (String remotePath) { 266 boolean result = false; 267 try { 268 // 鏈接至服務器 269 //result = ftpClient.changeWorkingDirectory(remotePath); 270 String [] dirs = remotePath.split("/"); 271 if(dirs!=null){ 272 String tempDir = ""; 273 for(String dir : dirs){ 274 tempDir += dir +"/"; 275 result = ftpClient.changeWorkingDirectory(tempDir); 276 if(!result){ 277 result = ftpClient.makeDirectory(dir); 278 ftpClient.changeWorkingDirectory(dir); 279 } 280 } 281 } 282 } catch (IOException e) { 283 e.printStackTrace(); 284 return false; 285 } 286 return true; 287 } 288 /** 289 * 檢測FTP服務器文件是否存在 290 * 服務器名稱 291 * @param remotePath 292 * 檢測文件存儲路徑 293 * @param fileName 294 * 檢測文件存儲名稱 295 * @return 296 * <b>true</b>:文件存在 297 * <br/> 298 * <b>false</b>:文件不存在 299 */ 300 public boolean checkFile (String remotePath, String fileName) { 301 boolean result = false; 302 try { 303 // 鏈接至服務器 304 result = connectToTheServer(remotePath); 305 // 判斷服務器是否鏈接成功 306 if (result) { 307 // 默認文件不存在 308 result = false; 309 // 獲取文件操做目錄下全部文件名稱 310 String[] remoteNames = ftpClient.listNames(); 311 // 循環比對文件名稱,判斷是否含有當前要下載的文件名 312 for (String remoteName: remoteNames) { 313 if (fileName.equals(remoteName)) { 314 result = true; 315 } 316 } 317 } 318 } catch (IOException e) { 319 e.printStackTrace(); 320 } finally { 321 // 登出服務器並斷開鏈接 322 ftpUtils.logout(); 323 } 324 return result; 325 } 326 327 /** 328 * 登出服務器並斷開鏈接 329 * 330 * @param ftp 331 * FTPClient對象實例 332 * @return 333 * <b>true</b>:操做成功 334 * <br/> 335 * <b>false</b>:操做失敗 336 */ 337 public boolean logout () { 338 boolean result = false; 339 if (null != is) { 340 try { 341 // 關閉輸入流 342 is.close(); 343 } catch (IOException e) { 344 e.printStackTrace(); 345 } 346 } 347 if (null != ftpClient) { 348 try { 349 // 登出服務器 350 result = ftpClient.logout(); 351 } catch (IOException e) { 352 e.printStackTrace(); 353 } finally { 354 // 判斷鏈接是否存在 355 if (ftpClient.isConnected()) { 356 try { 357 // 斷開鏈接 358 ftpClient.disconnect(); 359 } catch (IOException e) { 360 e.printStackTrace(); 361 } 362 } 363 } 364 } 365 return result; 366 } 367 368 public String getSiteName() { 369 return siteName; 370 } 371 372 public String getSaveFilePath() { 373 return saveFilePath; 374 } 375 }
第四步 用到的副類,真正作到任君品嚐 !!(重要程度:☆☆)
(1)IDGen工具類
1 /** 2 * 隨機ID工具類 3 */ 4 package com.xx.utils; 5 6 import java.io.Serializable; 7 import java.security.SecureRandom; 8 import java.text.DecimalFormat; 9 import java.util.Date; 10 import java.util.UUID; 11 12 import org.apache.shiro.session.Session; 13 import org.apache.shiro.session.mgt.eis.SessionIdGenerator; 14 import org.springframework.context.annotation.Lazy; 15 import org.springframework.stereotype.Service; 16 17 /** 18 * 封裝各類生成惟一性ID算法的工具類. 19 * @author ThinkGem 20 * @version 2013-01-15 21 */ 22 @Service 23 @Lazy(false) 24 public class IdGen implements SessionIdGenerator { 25 26 private static SecureRandom random = new SecureRandom(); 27 private static int num; 28 29 /** 30 * 封裝JDK自帶的UUID, 經過Random數字生成, 中間無-分割. 31 */ 32 public static String uuid() { 33 return UUID.randomUUID().toString().replaceAll("-", ""); 34 } 35 /** 36 * 生成投資編號 37 * @return 38 */ 39 public static String investNo(){ 40 String date = DateUtils.formatDateToStr("yyyyMMddHHmmss",new Date()); 41 if(num>999999){ 42 num = 0; 43 } 44 String numStr = new DecimalFormat("000000").format(num++); 45 return date.substring(2)+ numStr; 46 } 47 48 /** 49 * 使用SecureRandom隨機生成Long. 50 */ 51 public static long randomLong() { 52 return Math.abs(random.nextLong()); 53 } 54 55 56 57 @Override 58 public Serializable generateId(Session session) { 59 return IdGen.uuid(); 60 } 61 62 public static String getRandomName(int k){ 63 String chars = "abcdefghijklmnopqrstuvwxyz0123456789"; 64 StringBuilder sb = new StringBuilder(); 65 for (int i = 0; i < k; i++) { 66 sb.append(chars.charAt((int)(Math.random() * 36))); 67 } 68 return sb.toString(); 69 } 70 71 72 }
(2)ImageUtil工具類
1 package com.xx.utils; 2 3 import java.awt.AlphaComposite; 4 import java.awt.Color; 5 import java.awt.Font; 6 import java.awt.Graphics2D; 7 import java.awt.Image; 8 import java.awt.RenderingHints; 9 import java.awt.image.BufferedImage; 10 import java.io.File; 11 import java.io.FileOutputStream; 12 import java.io.InputStream; 13 import java.io.OutputStream; 14 15 import javax.imageio.ImageIO; 16 import javax.swing.ImageIcon; 17 18 import org.slf4j.Logger; 19 import org.slf4j.LoggerFactory; 20 21 /** 22 * 圖片處理類 23 * @author xx 24 */ 25 public class ImageUtils { 26 private final static Logger logger = LoggerFactory.getLogger(ImageUtils.class); 27 // 水印透明度 28 private static float alpha = 0.5f; 29 // 水印橫向位置 30 private static int positionWidth = 150; 31 // 水印縱向位置 32 private static int positionHeight = 300; 33 // 水印文字字體 34 private static Font font = new Font("宋體", Font.BOLD, 30); 35 // 水印文字顏色 36 private static Color color = Color.red; 37 38 /** 39 * 給圖片添加圖片水印 40 * @param iconPath 水印圖片路徑 41 * @param file 源文件 42 * @param targerPath 目標圖片路徑 43 * @param degree 水印圖片旋轉角度 44 */ 45 public static void markImageByIcon(String iconPath, File file, 46 String targerPath, Integer degree) { 47 OutputStream os = null; 48 try { 49 logger.info("水印圖片路徑:{}", iconPath); 50 logger.info("源文件:{}", file.getAbsolutePath()); 51 logger.info("目標圖片路徑:{}", targerPath); 52 Image srcImg = ImageIO.read(file); 53 54 BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null), 55 srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB); 56 57 // 獲得畫筆對象 58 Graphics2D g = buffImg.createGraphics(); 59 60 // 設置對線段的鋸齒狀邊緣處理 61 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 62 RenderingHints.VALUE_INTERPOLATION_BILINEAR); 63 64 g.drawImage(srcImg.getScaledInstance(srcImg.getWidth(null), srcImg 65 .getHeight(null), Image.SCALE_SMOOTH), 0, 0, null); 66 67 if (null != degree) { 68 // 設置水印旋轉 69 g.rotate(Math.toRadians(degree), 70 (double) buffImg.getWidth() / 2, (double) buffImg 71 .getHeight() / 2); 72 } 73 74 // 水印圖象的路徑 水印通常爲gif或者png的,這樣可設置透明度 75 ImageIcon imgIcon = new ImageIcon(iconPath); 76 77 // 獲得Image對象。 78 Image img = imgIcon.getImage(); 79 80 float alpha = 0.5f; // 透明度 81 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 82 alpha)); 83 84 // 表示水印圖片的位置 相對於中心店的寬高以及水印圖片寬高(img,x,y,width,height,obnull) 85 g.drawImage(img, buffImg.getWidth() / 6,buffImg.getHeight() / 3, buffImg.getWidth() / 2,buffImg.getHeight() / 4, null); 86 87 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); 88 89 g.dispose(); 90 91 os = new FileOutputStream(targerPath); 92 93 // 生成圖片 94 ImageIO.write(buffImg, "JPG", os); 95 96 logger.info("圖片完成添加水印"); 97 } catch (Exception e) { 98 e.printStackTrace(); 99 logger.error("圖片完成添加水印error:{}", e.getMessage()); 100 } finally { 101 try { 102 if (null != os) 103 os.close(); 104 } catch (Exception e) { 105 e.printStackTrace(); 106 } 107 } 108 } 109 110 /** 111 * 給圖片添加水印文字 112 * @param logoText 水印文字 113 * @param srcImgPath 原圖片路徑 114 * @param targerPath 目標圖片路徑 115 * @param degree 旋轉角度 116 */ 117 public static void markImageByText(String logoText, String srcImgPath, 118 String targerPath, Integer degree) { 119 120 InputStream is = null; 121 OutputStream os = null; 122 try { 123 // 一、源圖片 124 Image srcImg = ImageIO.read(new File(srcImgPath)); 125 BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null),srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB); 126 127 // 二、獲得畫筆對象 128 Graphics2D g = buffImg.createGraphics(); 129 // 三、設置對線段的鋸齒狀邊緣處理 130 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR); 131 g.drawImage(srcImg.getScaledInstance(srcImg.getWidth(null), srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0, null); 132 // 四、設置水印旋轉 133 if (null != degree) { 134 g.rotate(Math.toRadians(degree),(double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2); 135 } 136 // 五、設置水印文字顏色 137 g.setColor(color); 138 // 六、設置水印文字Font 139 g.setFont(font); 140 // 七、設置水印文字透明度 141 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,alpha)); 142 // 八、第一參數->設置的內容,後面兩個參數->文字在圖片上的座標位置(x,y) 143 g.drawString(logoText, positionWidth, positionHeight); 144 // 九、釋放資源 145 g.dispose(); 146 // 十、生成圖片 147 os = new FileOutputStream(targerPath); 148 ImageIO.write(buffImg, "JPG", os); 149 150 logger.info("圖片完成添加水印文字"); 151 152 } catch (Exception e) { 153 e.printStackTrace(); 154 } finally { 155 try { 156 if (null != is) 157 is.close(); 158 } catch (Exception e) { 159 e.printStackTrace(); 160 } 161 try { 162 if (null != os) 163 os.close(); 164 } catch (Exception e) { 165 e.printStackTrace(); 166 } 167 } 168 } 169 170 /** 171 * 判斷文件是否是圖片 172 * @param file 173 * @return 174 * @author guogf 175 */ 176 public static boolean isImage(File file) 177 { 178 boolean flag = false; 179 try 180 { 181 Image is = ImageIO.read(file); 182 if(null != is) 183 { 184 flag = true; 185 } 186 } catch (Exception e) 187 { 188 e.printStackTrace(); 189 } 190 return flag; 191 } 192 193 }
到此後臺處理函數已完整實現,如今須要將後臺返回的json串回調到前端編輯器來處理,寫入上傳容器框以及編輯器文章當中。
首先去找到umeditor.config.js 找到以下並修改:
1 //圖片上傳配置區 2 ,imageUrl:ctx+"/cms/article/upload" //圖片上傳提交地址 很重要!上傳提交地址,這裏配置成我剛纔寫的那個控制器函數 路徑很重要 ctx獲取的是當前域名 3 ,imagePath:"http://static.xx.com/" //圖片修正地址,對應剛纔我提到的域名配置的地方 必須配置!! 4 ,imageFieldName:"upfile" //圖片數據的key,若此處修改,須要在後臺對應文件修改對應參數 對應剛纔提到的上傳圖片的表單name 默認便可
配置好以後,後來調試發現 返回的json 串包含在pre標籤裏,編輯器腳本解析不了,報錯,因此,這裏還須要修改編輯器目錄 dialogs\image\image.js文件
1 uploadComplete: function(r){ 2 debugger; 3 var me = this; 4 try{ 5 var json = eval('('+$(r).html()+')'); //這裏須要把返回的字符串轉化成對象 pre對象,而後獲取裏面json串 6 Base.callback(me.editor, me.dialog, json.url, json.state); 7 }catch (e){ 8 var lang = me.editor.getLang('image'); 9 Base.callback(me.editor, me.dialog, '', (lang && lang.uploadError) || 'Error!'); 10 } 11 },
好了,到這裏基本完事了,咱們看下最終效果吧!
開始上傳效果圖:
拖曳或者上傳效果圖:
編輯器效果圖:
文章預覽效果圖:
這篇博文寫了挺長時間,手都酸了...以前有部分分享老是被移除首頁,因此,在格式排版上花很長時間..