- (本文原创,引用请注明出处--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="width: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;width:420px;height:415px;z-index:5;position:absolute;top:-420px;left:400px; 4 background-color:white;"> 5 <table border="0" style="width:392px;height:356px"> 6 <tr style="height:36px;"> 7 <td style="width:260px;width:36px;border: 0px solid red;" colspan="3"> 8 <table style="width:100%"> 9 <tr> 10 <td id="idTagFakeFileInput" style="width:80%"></td> 11 <td id="idTagFakeFileBtn" style="width:20%" align="center"> 12 <div id="" style="border:0px solid grey;width: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="width:100%" method="post" enctype="multipart/form-data" > 20 <input id="upload-btn" style="width: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="width: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="width:112px;height:152px;border:0px solid green;margin-top:100px;"> 39 <div>预览:</div> 40 <div id = "aa" style="width: 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="width:100%;height:30px;"> 49 <tr> 50 <td align="right"> 51 <div id="idQueryBtn" style="border:0px solid grey;width: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;width: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:\\JavaEE\\workspaces\\eclipseTest\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp4\\wtpwebapps\\zjInfoOS\\zjfxjk\\expertsLib\\photos 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 width: 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:\\a\\b\\1.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 }