jcrop+jquery+javaweb 实现头像裁剪、上传

  • (本文原创,引用请注明出处--zhangjieatbky)
  • 环境准备
    • 准备jquery、jcrop的js和css(官网获取)、jquery的文件上传下载组件
 1 <script type="text/javascript" src="<%=path %>/sparknet/manage/ui/accordion/jquery-1.12.4.min.js"></script>
 2 <link rel="stylesheet" href="ref/jquery.Jcrop.min.css"/>
 3 <script type="text/javascript" src="ref/jquery.color.js"></script>
 4 <script type="text/javascript" src="ref/jquery.Jcrop.min.js"></script>
 5 <!-- 文件上传下载组件 -->
 6 <script type="text/javascript" src="<%=path %>/zjfxjk/expertsLib/ref/jquery.ui.widget.js"></script>
 7 <script type="text/javascript" src="<%=path %>/zjfxjk/expertsLib/ref/jquery.iframe-transport.js"></script>
 8 <script type="text/javascript" src="<%=path %>/zjfxjk/expertsLib/ref/jquery.fileupload.js"></script>
 9 <script type="text/javascript" src="<%=path %>/zjfxjk/expertsLib/ref/jquery.fileupload-process.js"></script>
10 <script type="text/javascript" src="<%=path %>/zjfxjk/expertsLib/ref/jquery.fileupload-validate.js"></script>
11 <script type="text/javascript" src="<%=path %>/zjfxjk/expertsLib/ref/jquery.form.js"></script>
12 <script type="text/javascript" src="<%=path %>/zjfxjk/expertsLib/ref/signTrans.js"></script>
    • html代码
 1 <div id="idDivShield2" class="opacity" style="100%;height:100%;z-index:4;top:0px;left:0px;position:absolute;
 2             background-color:#BEBEBE;display:none;"></div>
 3         <div id="idPhotoEditWin" class="opacity2"  style="border: 0px solid red;420px;height:415px;z-index:5;position:absolute;top:-420px;left:400px;
 4         background-color:white;">
 5             <table border="0" style="392px;height:356px">
 6                 <tr style="height:36px;">
 7                     <td  style="260px;36px;border: 0px solid red;" colspan="3">
 8                         <table style="100%">
 9                             <tr>
10                                 <td id="idTagFakeFileInput" style="80%"></td>
11                                 <td id="idTagFakeFileBtn" style="20%" align="center">
12                                     <div id="" style="border:0px solid grey;70px;height:20px;padding-top:3px;margin-right:0px;
13                                          background-color: #4178be;color:white;cursor: pointer;" align="center" onclick="methods.fakePhotoUpload()">
14                                            <span>选择文件</span>
15                                      </div>    
16                                 </td>
17                             </tr>
18                         </table>
19                         <form id="upload-file" style="100%" method="post" enctype="multipart/form-data" >  
20                             <input id="upload-btn"  style="100%;display:none;" type="file" name="file"  value="sss" onchange="methods.fileUpload()" />  
21                         </form>  
22                     </td>
23                 </tr>
24                 <tr style="height:320px;">
25                     <td>
26                         <div id="idTagDivPhoto" style="260px;height:300px;border:1px solid #ececec;">
27                             <!-- <img id = "target" src="none.png" width="240px" height="300px" class="jcrop-preview" alt="附件"> -->
28                             <!-- 图片长宽高隐藏域 -->
29                             <input type="hidden" id="x" name="x" /> 
30                             <input type="hidden" id="y" name="y" /> 
31                             <input type="hidden" id="w" name="w" /> 
32                             <input type="hidden" id="h" name="h" />
33                             <input type="hidden" id="boundx" name="boundx" >
34                             <input type="hidden" id="boundy" name="boundy" >
35                         </div>
36                     </td>
37                     <td colspan="2">
38                         <div style="112px;height:152px;border:0px solid green;margin-top:100px;">
39                              <div>预览:</div>
40                              <div id = "aa" style=" 112px;height: 132px;overflow: hidden;border:1px solid #ececec" >
41                                    <!-- <img id = "preview" src="none.png" width="112px" height="132px" class="jcrop-preview" alt="预览" > -->
42                              </div>
43                         </div>
44                     </td>
45                 </tr>
46                 <tr style="height:30px;">
47                     <td colspan="3" align="center">
48                         <table style="100%;height:30px;">
49                             <tr>
50                                 <td align="right">
51                                     <div id="idQueryBtn" style="border:0px solid grey;50px;height:20px;padding-top:3px;margin-right:10px;
52                                          background-color: #4178be;color:white;cursor: pointer;" align="center" onclick="methods.realPhotoUpload()">
53                                            <span>上传</span>
54                                      </div>    
55                                 </td>
56                                 <td align="left">
57                                     <div id="idQueryBtn" style="border:0px solid grey;50px;height:20px;padding-top:3px;margin-right:10px;
58                                          background-color: #4178be;color:white;cursor: pointer;" align="center" onclick="methods.closePhotoEditWin()">
59                                            <span>关闭</span>
60                                      </div>
61                                 </td>
62                             </tr>
63                         </table>
64                     </td>
65                 </tr>
66             </table>
67         </div>

 

      • 效果图
      • js逻辑部分,弹框+上传原图+裁剪坐标
      •  1 //图像编辑窗口
         2             popPhotoEditWin : function(){
         3                 $('#upload-btn').val('');
         4                 Ext.getCmp('idFakeFileInput').setValue('');
         5                 var account = Ext.getCmp('idExpertCode').getValue();
         6                 if(!account){
         7                     Ext.MessageBox.alert("提示","请先选定专家账号");
         8                     return;
         9                 }
        10                 //每次打开,将大图删除
        11                 if($('#idPhotoEditWin').data('photoName')){
        12                     $.ajax({
        13                         url:getPath()+"/ExpertLibController.json?deleteOriginalImage=true",    // $('#idPhotoEditWin').data('photoName',obj['msg']);
        14                         data:{originalImageName:$('#idPhotoEditWin').data('photoName')},
        15                         type:'post',
        16                         async:false,
        17                         success:function(e){
        18                             $('#idPhotoEditWin').removeData('photoName');
        19                         }
        20                     });
        21                 }
        22                 $('#idTagDivPhoto').prepend('<img id = "target" src="none.png" width="240px" height="300px" class="jcrop-preview">');
        23                 $('#aa').prepend('<img id = "preview" src="none.png" width="112px" height="132px" class="jcrop-preview" alt="预览" >');
        24                 $('#idDivShield2').show();
        25                 $('#idPhotoEditWin').animate({top:'70px'},500);
        26                 $('#idPhotoEditWin').scrollTop(0);
        27             },
         1 //onchange事件
         2             fileUpload : function(){
         3                 debugger;
         4                 if(!$('#upload-btn').val())
         5                     return;
         6                 Ext.getCmp('idFakeFileInput').setValue($('#upload-btn').val());
         7                 var account = Ext.getCmp('idExpertCode').getValue();
         8                 $('#idTagDivPhoto img').remove();                    //移除jcrop的渲染
         9                 $('#idTagDivPhoto div').remove();
        10                 $('#aa img').remove();
        11                 $('#idTagDivPhoto').prepend('<img id = "target" src="none.png" width="240px" height="300px" class="jcrop-preview">');
        12                 $('#aa').prepend('<img id = "preview" src="none.png" width="112px" height="132px" class="jcrop-preview" alt="预览" >');
        13                 var type = $('#upload-btn').val().split('.')[$('#upload-btn').val().split('.').length-1];
        14                 if(type.toLowerCase()!='jpg' && type.toLowerCase()!='png'){
        15                     Ext.MessageBox.alert("提示","请选择 jpg 或者 png 格式的图片");
        16                     $('#upload-btn').val('');
        17                     Ext.getCmp('idFakeFileInput').setValue('');
        18                     return;
        19                 }
        20                 if($('#upload-btn').val()){
        21                     var form = $('#upload-file');
        22                     var options  = {    
        23                             url:getPath()+'/ExpertLibController.json?photoUpload=true',    
        24                             type:'post',    
        25                             data : {
        26                                 userAccount:account,
        27                                 state:'original',
        28                                 oldName:$('#idPhotoEditWin').data('photoName')
        29                             },
        30                             success:function(data){
        31                                 debugger;
        32                                  var obj = Ext.util.JSON.decode(data);
        33                                  if(obj['success']=='false'){
        34                                      Ext.MessageBox.alert("提示",obj['msg']);
        35                                      $('#upload-btn').val('');
        36                                      Ext.getCmp('idFakeFileInput').setValue('');
        37                                      return;
        38                                  }
        39                                  //D:JavaEEworkspaceseclipseTest.metadata.pluginsorg.eclipse.wst.server.core	mp4wtpwebappszjInfoOSzjfxjkexpertsLibphotos
        40                                  $('#target').attr('src','photos/'+obj['msg']+'');
        41                                  $('#preview').attr('src','photos/'+obj['msg']+'');
        42                                  $('#idPhotoEditWin').data('photoName',obj['msg']);            //注意,在头像编辑窗口中保存该属性
        43                                  methods.jcropTackle();
        44                             }
        45                         };
        46                     form.ajaxSubmit(options);
        47                 }
        48             },
         1 //实际大小头像的上传
         2             realPhotoUpload:function(){
         3                 if(!$('#upload-btn').val()){
         4                     Ext.MessageBox.alert("提示","请先上传头像");
         5                     return;
         6                 }
         7                 var accountPhotoName0 = $('#idPhotoEditWin').data('photoName');        //大图
         8                 var oldRealPhoto0 = accountPhotoName0;
         9                 if(vars.selectArea[2]==0 || vars.selectArea[3]==0){
        10                     Ext.MessageBox.alert("提示","请选中有效区域");
        11                     return;
        12                 }
        13                 debugger;
        14                 $.ajax({
        15                     url:getPath()+"/ExpertLibController.json?photoSelected=true",
        16                     data:{oldRealPhoto:oldRealPhoto0,accountPhotoName:accountPhotoName0,x:vars.selectArea[0],y:vars.selectArea[1],w:vars.selectArea[2],h:vars.selectArea[3]},
        17                     type:'post',
        18                     async:false,
        19                     success:function(e){
        20                         //未做success的判断
        21                         $('#idPopModifyWin').data('realPhotoName',e['bean']);        //注意,这是包含original中的
        22                         methods.closePhotoEditWin();
        23 //                        $('#idTagPopWinPhoto').attr('src','');
        24                         $('#idTagPopWinPhoto').attr('src','photos/'+e['bean']+'');
        25                     }
        26                 });
        27             },
        28             //关闭图像编辑窗口
        29             closePhotoEditWin : function(){
        30                 $('#idPhotoEditWin').animate({top:'-485px'},500,function(){
        31                     $('#idDivShield2').hide();
        32                 });
        33                 $('#idTagDivPhoto img').remove();                    //移除jcrop的渲染
        34                 $('#idTagDivPhoto div').remove();
        35                 $('#aa img').remove();
        36 //                $('#idPopModifyWin').removeData('photoName');        //移除当前窗口的属性
        37             },
        38             jcropTackle : function(path){
        39               var option = {
        40                     x:40,
        41                     y:20,
        42                     w:98,
        43                     h:115,
        44                     t:'target',
        45                     p:'preview',
        46                     o:'aa'
        47                   }
        48               function updatePreview(obj){
        49                   vars.selectArea.length=0;
        50                     if (parseInt(obj.w) > 0){
        51                         var rx = $('#'+option['o']).width()/ obj.w;
        52                         var ry = $('#'+option['o']).height()/ obj.h;
        53                         $('#'+option['p']).css({
        54                              Math.round(rx*$('#'+option['t']).width()) + 'px',
        55                             height: Math.round(ry*$('#'+option['t']).height()) + 'px',
        56                             marginLeft: '-' + Math.round(rx * obj.x) + 'px',
        57                             marginTop: '-' + Math.round(ry * obj.y) + 'px'
        58                         });
        59                     }
        60                     vars.selectArea.push(obj.x);
        61                     vars.selectArea.push(obj.y);
        62                     vars.selectArea.push(obj.w);
        63                     vars.selectArea.push(obj.h);
        64                  }
        65                $('#'+option['t']).Jcrop({
        66                    onChange: updatePreview,
        67                    onSelect: updatePreview,
        68                    aspectRatio: 140/165,
        69                    minSize:[98,115],
        70                    maxSize:[588,693],
        71                    setSelect: [option['x'],option['y'],option['w'],option['h'] ]
        72 //                   bgFade:   true
        73 //                     bgOpacity: .5
        74                 });
        75             },
      • 后台处理:文件上传+图像裁剪
      •  1 public EditJsonX fileUpload(HttpServletRequest request){
         2         EditJsonX editJson = new EditJsonX();
         3         System.out.println("Accessed");
         4         String savePath = request.getSession().getServletContext().getRealPath("/")+"zjfxjk\expertsLib\photos\";
         5         String userAccount = "",state="";
         6         File file = new File(savePath);
         7         if(!file.exists() && !file.isDirectory()){
         8             System.out.println("目录不存在,创建该目录");
         9             file.mkdir();
        10         }
        11         String message ="",uniqueFilename="",oldName="";            //提示信息
        12         
        13         try{
        14             DiskFileItemFactory factory = new DiskFileItemFactory();
        15             ServletFileUpload upload = new ServletFileUpload(factory);        //文件上传解析器
        16             upload.setHeaderEncoding("UTF-8");
        17             if(!ServletFileUpload.isMultipartContent(request)){
        18                 //按照传统方式获取表单数据,非文件内容
        19                 return null;
        20             }
        21             //使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
        22             List<FileItem> list = upload.parseRequest(request);
        23             for(FileItem item : list){
        24                 //如果fileitem中封装的是普通输入项的数据
        25                 if(item.isFormField()){
        26                     String name = item.getFieldName();
        27                     //解决普通输入项的数据的中文乱码问题
        28                     String value = item.getString("UTF-8");
        29                     if(name.equals("userAccount")){
        30                         userAccount=value;
        31                     }else if(name.equals("state")){
        32                         state=value;
        33                     }else if(name.equals("oldName")){
        34                         oldName=value;
        35                     }
        36 //                    uniqueFilename = value;
        37                     //value = new String(value.getBytes("iso8859-1"),"UTF-8");
        38                     System.out.println(name + "=" + value);
        39                 }
        40             }
        41             for(FileItem item : list){
        42                 if(!item.isFormField()){
        43                     //如果fileitem中封装的是上传文件
        44                     //得到上传的文件名称,
        45                     String filename = item.getName();
        46                     if(item.getSize()>1024*200){
        47                         editJson.setSuccess(false);
        48                         editJson.setBean("上传文件大小不能超过200kb");
        49                         return editJson;
        50                     }else if(item.getSize()<1024*10){
        51                         editJson.setSuccess(false);
        52                         editJson.setBean("上传文件大小不能小于10kb");
        53                         return editJson;
        54                     }
        55                     System.out.println(filename);
        56                     if(filename==null || filename.trim().equals("")){
        57                         continue;
        58                     }
        59                     String [] filetypes = filename.split("\.");
        60                     String fileType = filetypes[filetypes.length-1];
        61                     if(!fileType.equals("jpg") && !fileType.equals("pdf") && !fileType.equals("doc") && !fileType.equals("docx")){
        62                         editJson.setSuccess(false);
        63                         editJson.setBean("格式错误,请使用*.jpg、*.png 的文件");
        64                         return editJson;
        65                     }
        66                     //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:a1.txt,而有些只是单纯的文件名,如:1.txt
        67                     //处理获取到的上传文件的文件名的路径部分,只保留文件名部分
        68                     //UUID.randomUUID().toString().replaceAll("-", "")
        69                     uniqueFilename = userAccount+state+"@"+UUID.randomUUID().toString().replaceAll("-", "")+"."
        70                             +filename.substring(filename.lastIndexOf("\")+1).split("\.")[1];
        71                     
        72                     //获取item中的上传文件的输入流
        73                     InputStream in = item.getInputStream();
        74                     //创建一个文件输出流
        75                     FileOutputStream out = new FileOutputStream(savePath + uniqueFilename);
        76                     IOUtils.copy(in, out);
        77                     in.close();
        78                     out.close();
        79                     //删除处理文件上传时生成的临时文件
        80 //                    item.delete();
        81                     message = "文件上传成功!";
        82                     new File(savePath+oldName).delete();            //删除旧头像
        83                     System.out.println(message);
        84                 }
        85             }
        86         }catch(Exception e){
        87             message= "文件上传失败!";
        88             System.out.println(message);
        89             throw new RuntimeException("上传文件过程中出现错误",e);
        90         }
        91         editJson.setSuccess(true);
        92         editJson.setBean(uniqueFilename);
        93         return editJson;
        94     }
      • 头像编辑+保存
      •  1     /**
         2      * 头像编辑
         3      * @param request
         4      * @param response
         5      * @return
         6      */
         7     @ResponseBody
         8     @RequestMapping(params="photoSelected")
         9     public EditJsonX photoSelected(HttpServletRequest request, HttpServletResponse response){
        10         EditJsonX editJsonX = new EditJsonX();
        11         //包含了可能的文件后缀名,这是原始图片,这个文件名中有 original。例如,18521452148original.jpg
        12         String accountPhotoName = request.getParameter("accountPhotoName");
        13         String oldRealPhoto = StringUtil.nullToEmpty(request.getParameter("oldRealPhoto"));
        14         String savePath = request.getSession().getServletContext().getRealPath("/")+"zjfxjk\expertsLib\photos\";
        15         String pSavePath = savePath+accountPhotoName;
        16         int x = (int)Math.round(Double.parseDouble(request.getParameter("x")));
        17         int y = (int)Math.round(Double.parseDouble(request.getParameter("y")));
        18         int w = (int)Math.round(Double.parseDouble(request.getParameter("w")));
        19         int h = (int)Math.round(Double.parseDouble(request.getParameter("h")));
        20         abscut(accountPhotoName,pSavePath, x, y,w,h, request);
        21         editJsonX.setSuccess(true);
        22         accountPhotoName = accountPhotoName.replace("original", "real");
        23         editJsonX.setBean(accountPhotoName);
        24         //删除原图
        25         if(!oldRealPhoto.equals(""))
        26             new File(savePath+oldRealPhoto).delete();
        27         return editJsonX;
        28     }
         1 /**
         2      * 截取选中的区域,并保存
         3      * @param srcImageFile
         4      * @param x
         5      * @param y
         6      * @param w
         7      * @param h
         8      */
         9     private static void abscut(String accountPhotoName ,String srcImageFile,int x,int y,int destWidth,int destHeight,HttpServletRequest request){
        10         try{
        11             Image img;
        12             ImageFilter cropFilter;
        13             BufferedImage bi = ImageIO.read(new File(srcImageFile));            //读取源文件
        14             int srcWidth = bi.getWidth(); // 源图宽度
        15             int srcHeight = bi.getHeight(); // 源图高度
        16             if (srcWidth >= destWidth && srcHeight >= destHeight) {
        17                 Image image = bi.getScaledInstance(srcWidth, srcHeight,Image.SCALE_DEFAULT);
        18 
        19                 /* ****************************************
        20                 *  判断原图的宽高和DIV宽高的大小
        21                 *  根据图片外层DIV的宽度,选择的起始点则有相对变化
        22                 *************************************** */
        23                 int x1 = (x*srcWidth)/240;
        24                 int y1 = (y*srcHeight)/300;
        25 //                int w = destWidth*(srcWidth/240);
        26                 int w = (destWidth*srcWidth)/240;
        27 //                int h = destHeight*(srcHeight/300);
        28                 int h = (srcHeight*destHeight)/300;
        29 
        30                 // 四个参数分别为图像起点坐标和宽高
        31                 // 即: CropImageFilter(int x,int y,int width,int height)
        32                 cropFilter = new CropImageFilter(x1, y1, w, h);
        33                 img = Toolkit.getDefaultToolkit().createImage(
        34                 new FilteredImageSource(image.getSource(), cropFilter));
        35                 BufferedImage tag = new BufferedImage(w, h,BufferedImage.TYPE_INT_RGB);
        36                 Graphics g = tag.getGraphics();
        37                 g.drawImage(img, 0, 0, null); // 绘制缩小后的图
        38                 g.dispose();
        39                 // 输出为文件
        40                 accountPhotoName = accountPhotoName.replace("original", "real");
        41                 String savePath = request.getSession().getServletContext().getRealPath("/")+"zjfxjk\expertsLib\photos\"+accountPhotoName;
        42                 ImageIO.write(tag, "JPEG", new File(savePath));
        43             }
        44         }catch (Exception e) {
        45             e.printStackTrace();
        46         }
        47     }

      • 在做人员库的时候,为了保证图片的加载速度,可以将这些小文件保存在服务器的磁盘上,但需要对文件进行有效关闭,避免垃圾文件的产生。因此需要配上文件处理方法
    •  1 //用户检查自己的original文件并删除
       2     public void deleteOriginalFile(String username0,HttpServletRequest request){
       3         String username = username0;
       4         List<Map<String,Object>> list = expertLibDao.getFileName(new Object[]{username});
       5         if(list.size()==0)
       6             return;
       7         String filename = list.get(0).get("FILE_NAME")+"";
       8         String path = request.getSession().getServletContext().getRealPath("/")+"zjfxjk\expertsLib\photos\";
       9         String [] names2 = new File(path).list();
      10         int len = names2.length;
      11         for(int i=0;i<len;i++){
      12             if(names2[i].contains(username) && !names2[i].equals(filename))
      13                 new File(path+names2[i]).delete();
      14         }
      15     }
      16     
      17     //比较硬盘上的文件名和附件表中的文件名
      18     public void compareFilename(HttpServletRequest request) throws Exception{
      19         List<Map<String,Object>> listMap = expertLibDao.getFilenames();
      20         int size = listMap.size();
      21         String [] names1 = new String[size];        //数据库中的filename
      22         for(int i=0;i<size;i++)
      23             names1[i]=(listMap.get(i).get("FILE_NAME")+"");
      24         String path = request.getSession().getServletContext().getRealPath("/")+"zjfxjk\expertsLib\photos\";
      25         String [] names2 = new File(path).list();
      26         int len = names2.length;
      27         for(int i = 0;i < size;i++){
      28             if(len>0){
      29                 for(int j=0;j<len;j++){
      30                     int count = 0;
      31                     if(!names2[j].equals(names1[i])){
      32                         //将磁盘上的文件和数据库中的文件做比较
      33                         count++;
      34                         if(count==len){
      35                                 List<InputStream> temp = expertLibDao.writeToDisk(new Object[]{names2[j]});
      36                                 if(temp.size()==0)
      37                                     continue;
      38                                 InputStream is = temp.get(0); 
      39                                 FileOutputStream fos = new FileOutputStream(path+names2[j]);
      40                                 IOUtils.copy(is,fos);
      41                                 System.out.println("将文件:"+names2[j]+" 写入到磁盘中");
      42                         }
      43                     }else{
      44                         break;
      45                     }
      46                 }
      47             }else{
      48                 List<InputStream> temp = expertLibDao.writeToDisk(new Object[]{names1[i]});
      49                 if(temp.size()==0)
      50                     continue;
      51                 InputStream is = temp.get(0); 
      52                 FileOutputStream fos = new FileOutputStream(path+names1[i]);
      53                 IOUtils.copy(is,fos);
      54                 System.out.println("将文件:"+names1[i]+" 写入到磁盘中");
      55             }
      56         }
      57         for(int i=0;i<len;i++){
      58             for(int j=0;j<size;j++){
      59                 //将数据库中的文件与磁盘上的文件做比较
      60                 int count = 0;
      61                 if(!names1[j].equals(names2[i]) && names2[i].contains("real")){
      62                     count++;
      63                     if(count==size){
      64                         new File(path+names2[i]).delete();
      65                     }
      66                 }else{
      67                     break;
      68                 }
      69             }
      70         }
      71     }
原文地址:https://www.cnblogs.com/zhangjieatbky/p/8137183.html