【完整靠谱版】结合公司项目,仔细总结自己使用百度编辑器实现FTP上传的完整过程

说在前面

    工作中会遇到很多需要使用富文本编辑器的地方,比如我现在发布这篇文章离不开这个神器,而且现在网上编辑器太多了。记得之前,由于工作需要自己封装过一个编辑器的公共插件,是用ckeditor改版的,目的是要兼容公司所有项目,使用方便。废话不多说,今天写这篇文章,一是总结自己学习复习,二是关于FTP上传官方资料太少,也便于他人少趟坑,我在这里会说的很细很明白,希望亲们以后不要中枪了!

关于编辑器的简单部署

     去官网下载后,我们需要把下载的编辑器文件夹,摘一部分放到项目中,下载之后的目录,如下图(我这里用的是jsp简化版 1.2.2)

        我在外面新建了个插件目录umeditor,如下图:

 

       除了jsp文件夹,其余拷到项目静态资源的目录中,然后 我们来分析jsp文件夹都有哪些东东?

       这里,我把那两个jar包带入到项目中,这里我改了名字,方便导入,fileupload那个jar包项目之前就有。如下图:

    

      接下来,就是页面调用了,很简单,首先将编辑器所需要的样式和脚本文件引入:

/**以上省略,这里引入到页面头部**/
<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>

    至此基本的工作已做完,上述相信大部分搞开发的同胞们,都没问题吧!效果图如下:

 

关于编辑器的后台实现

        官方下载给的后台处理文件除了必要的jar外有三个文件:

       (1) Uploader.java 文件

       该文件主封装了一个文件上传对象,包括上传后需要返回的参数、状态、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             // 1、源图片
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             // 2、得到画笔对象
128             Graphics2D g = buffImg.createGraphics();
129             // 3、设置对线段的锯齿状边缘处理
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             // 4、设置水印旋转
133             if (null != degree) {
134                 g.rotate(Math.toRadians(degree),(double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2);
135             }
136             // 5、设置水印文字颜色
137             g.setColor(color);
138             // 6、设置水印文字Font
139             g.setFont(font);
140             // 7、设置水印文字透明度
141             g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,alpha));
142             // 8、第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y)
143             g.drawString(logoText, positionWidth, positionHeight);
144             // 9、释放资源
145             g.dispose();
146             // 10、生成图片
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标签里,编辑器脚本解析不了,报错,所以,这里还需要修改编辑器目录 dialogsimageimage.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         },

    好了,到这里基本完事了,我们看下最终效果吧!

    开始上传效果图:

 

      拖曳或者上传效果图:

    

       编辑器效果图:

                                  

       文章预览效果图:

说在后面

      这篇博文写了挺长时间,手都酸了...之前有部分分享总是被移除首页,所以,在格式排版上花很长时间..

原文地址:https://www.cnblogs.com/sybboy/p/5733719.html