【完整靠譜版】結合公司項目,仔細總結本身使用百度編輯器實現FTP上傳的完整過程

說在前面

    工做中會遇到不少須要使用富文本編輯器的地方,好比我如今發佈這篇文章離不開這個神器,並且如今網上編輯器太多了。記得以前,因爲工做須要本身封裝過一個編輯器的公共插件,是用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         },

 

    好了,到這裏基本完事了,咱們看下最終效果吧!

 

    開始上傳效果圖:

 

 

      拖曳或者上傳效果圖:

    

 

       編輯器效果圖:

                                  

       文章預覽效果圖:

 

 

 

說在後面

      這篇博文寫了挺長時間,手都酸了...以前有部分分享老是被移除首頁,因此,在格式排版上花很長時間..

相關文章
相關標籤/搜索