jquery.Jcrop结合JAVA后台实现图片裁剪上传实例
本文介绍了头像裁剪上传功能,用到的技术有 jQuery,springmvc,裁剪插件用的是jcrop(中间遇到很多坑,最终跨越)。
图片上传步骤:
1.用户选择图片
2.将图片传入后台:用户选择图片的时候选择的是各种各样的,但是我们的网页显示图片大小是有限的,所以我们就要在用户选择图片之后将图片添加到后台进行压缩,压缩成我们想要的大小,之后再显示到页面才好
3.利用jcrop裁剪工具对图片进行裁剪并且实时预览
4.点击确定按钮将裁剪用到的参数传入后台,后台图片进行剪切,之后缩放成我们需要的格式
5.最后将图片路径传到前台进行展示
前台页面代码为:
<scriptsrc="js-jcrop/jquery.min.js"></script> <scriptsrc="js-jcrop/jquery.Jcrop.js"></script> <scriptsrc="js/jquery-form.js"></script> <linkrel="stylesheet"href="../css/jquery.Jcrop.css"type="text/css"/> <styletype="text/css"> /*控制预览区域大小*/ #preview-pane.preview-container{ width:110px; height:110px; overflow:hidden; } #targetDiv{ width:400px; height:400px; background-color:#f7fdff; } </style> <dlclass="dialogBoxD_uploadLogo"> <dtclass="dialogHeader"> <spanclass="title">头像上传</span> </dt> <ddclass="dialogBody"> <dlclass="bisinessLogo"> <dtclass="title">预览</dt> <ddclass="img"> <divid="preview-pane"> <divclass="preview-container"> <imgsrc=""id="target2"class="jcrop-preview"alt="未选择图片"/> </div> </div> </dd> <ddclass="tc">尺寸:110*110px</dd> </dl> <dlclass="bisinessInfo"> <dtclass="btnBox02"> <formid="fileUp"action="/file/img/upload"method="post"enctype="multipart/form-data"target="ifm"> <aclass="btnGray"href="javascript:;"> <spanclass="text"id="format">选择图片</span> <bclass="bgR"></b> <inputtype="file"id="file_upload"class="inputFile"name="userphoto"/> <inputtype="hidden"id="w"name="w"/> <inputtype="hidden"id="h"name="h"/> <inputtype="hidden"id="x"name="x"/> <inputtype="hidden"id="y"name="y"/> </a> </form> </dt> <ddclass="info"> 请从本地选择一张照片,支持jpg,png格式<spanid="msg"></span> <divid="targetDiv"> <imgsrc=""id="target"width="400"height="400"alt="未选择图片"/> </div> </dd> </dl> </dd> <inputtype="hidden"id="filePathInput"value=""/> <ddclass="dialogBottom"> <aclass="btnBluebtn_confirm"href="javascript:;"onclick="photoSummit();"><spanclass="text">确定</span><bclass="bgR"></b></a> <aclass="btnGraybtn_cancel"href="javascript:;"onclick="hideDialog();"><spanclass="text">取消</span><bclass="bgR"></b></a> </dd> </dl>
1.选择图片
<imgsrc=""id="target"width="400"height="400"alt="未选择图片"/>
2.提交:首先大家知道文件上传的时候用到的标签为:<inputtype="file"/> 但是有时候我们需要用ajax提交文件并且异步提交,我们如果是用form表单提交的话就不是异步,这样我们回到页面就刷新页面,非常的不方便,但是现在ajax还不能支持文件提交的方式,这时候我们就用到了jquery-form.js,这个文件支持我们用ajax提交文件,代码为:
$("#fileUp").<spanstyle="color:#ff0000;">ajaxSubmit</span>({ type:"POST", url:"/file/img/upload", dataType:"json", contentType:"application/json", success:function(parameter){ $("#target2").attr('src','/upload/'+parameter.fileName); $("#filePathInput").val('/upload/'+parameter.fileName); if($("#format").text()=="重新上传"){ jcrop_api.destroy() } $("#format").text("重新上传"); //启动jcrop支持 openJcrop('/upload/'+parameter.fileName); }, error:function(data){ alert("ajax传输发生错误!!!"); } });
这样就能将文件用ajax的方式提交到后台,注意这里用的是ajaxSubmit,这个方法对应jquery-form.js,后台代码为:
packagecom.quanshi.ums.gate.view.rest.controllers; importjava.io.IOException; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; importjavax.servlet.http.HttpSession; importorg.slf4j.Logger; importorg.slf4j.LoggerFactory; importorg.springframework.stereotype.Controller; importorg.springframework.web.bind.annotation.RequestMapping; importorg.springframework.web.bind.annotation.RequestMethod; importorg.springframework.web.bind.annotation.RequestParam; importorg.springframework.web.bind.annotation.ResponseBody; importorg.springframework.web.multipart.MultipartFile; importcom.quanshi.ums.gate.persistence.entities.Parameters; importcom.quanshi.ums.gate.view.rest.ImgEditor; /** *图像上传和修改相关类 *@authorkunpeng.zhao * */ @Controller @RequestMapping(value="/file") publicclassFileEditorController{ <spanstyle="white-space:pre"></span>ImgEditorimgEditor=newImgEditor(); <spanstyle="white-space:pre"></span>publicStringfilePathFinal=""; <spanstyle="white-space:pre"></span>privateLoggerlogger=LoggerFactory.getLogger(FileEditorController.class); <spanstyle="white-space:pre"></span>@RequestMapping(value="/img/cutandscale",method=RequestMethod.POST) <spanstyle="white-space:pre"></span>public@ResponseBodyintcutAndscaleimg( <spanstyle="white-space:pre"></span>@RequestParam("w")intw, <spanstyle="white-space:pre"></span>@RequestParam("h")inth, <spanstyle="white-space:pre"></span>@RequestParam("x")intx, <spanstyle="white-space:pre"></span>@RequestParam("y")inty <spanstyle="white-space:pre"></span>){ <spanstyle="white-space:pre"></span>imgEditor.cut(filePathFinal,filePathFinal,x,y,w,h); <spanstyle="white-space:pre"></span>imgEditor.scale(filePathFinal,filePathFinal,110,110,false); <spanstyle="white-space:pre"></span>return1; <spanstyle="white-space:pre"></span>} <spanstyle="white-space:pre"></span> <spanstyle="white-space:pre"></span> @RequestMapping(value="/img/upload",method=RequestMethod.POST) public@ResponseBodyParametersaddImage( <spanstyle="white-space:pre"></span>@RequestParam("userphoto")MultipartFilefile, <spanstyle="white-space:pre"></span>HttpServletRequestrequest, <spanstyle="white-space:pre"></span>HttpServletResponseresponse, <spanstyle="white-space:pre"></span>HttpSessionsession <spanstyle="white-space:pre"></span>){ <spanstyle="white-space:pre"></span>StringfilePath=""; <spanstyle="white-space:pre"></span>try{ <spanstyle="white-space:pre"></span>//上传原图 <spanstyle="white-space:pre"></span>filePath=imgEditor.uploadFile(file,request,session); <spanstyle="white-space:pre"></span>filePathFinal=filePath; <spanstyle="white-space:pre"></span>//将图片压缩成指定大小 <spanstyle="white-space:pre"></span>imgEditor.zoomImage(filePath,filePath,400,400); <spanstyle="white-space:pre"></span>}catch(IOExceptione){ <spanstyle="white-space:pre"></span>e.printStackTrace(); <spanstyle="white-space:pre"></span>} logger.info("filePath:"+filePath); Parametersparameter=newParameters(); parameter.setFileName(imgEditor.getFileName(file,request,session)); <spanstyle="white-space:pre"></span>returnparameter; } }
我在这规定图片在前台展示的大小为400*400,用到的图片裁剪压缩等的工具类为:
packagecom.quanshi.ums.gate.view.rest; importjava.awt.Color; importjava.awt.Graphics; importjava.awt.Graphics2D; importjava.awt.Image; importjava.awt.Toolkit; importjava.awt.geom.AffineTransform; importjava.awt.image.AffineTransformOp; importjava.awt.image.BufferedImage; importjava.awt.image.CropImageFilter; importjava.awt.image.FilteredImageSource; importjava.awt.image.ImageFilter; importjava.io.File; importjava.io.IOException; importjava.text.SimpleDateFormat; importjava.util.Date; importjavax.imageio.ImageIO; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpSession; importorg.springframework.security.core.context.SecurityContextHolder; importorg.springframework.web.multipart.MultipartFile; publicclassImgEditor{ /** *改变图片尺寸 *@paramsrcFileName源图片路径 *@paramtagFileName目的图片路径 *@paramwidth修改后的宽度 *@paramheight修改后的高度 */ publicvoidzoomImage(StringsrcFileName,StringtagFileName,intwidth,intheight){ try{ BufferedImagebi=ImageIO.read(newFile(srcFileName)); BufferedImagetag=newBufferedImage(width,height,BufferedImage.TYPE_INT_RGB); tag.getGraphics().drawImage(bi,0,0,width,height,null); ImageIO.write(tag,"jpg",newFile(tagFileName));//画图 }catch(IOExceptione){ e.printStackTrace(); } } /** *缩放图像(按高度和宽度缩放) *@paramsrcImageFile源图像文件地址 *@paramresult缩放后的图像地址 *@paramheight缩放后的高度 *@paramwidth缩放后的宽度 *@parambb比例不对时是否需要补白:true为补白;false为不补白; */ publicvoidscale(StringsrcImageFile,Stringresult,intheight,intwidth,booleanbb){ try{ doubleratio=0.0;//缩放比例 Filef=newFile(srcImageFile); BufferedImagebi=ImageIO.read(f); Imageitemp=bi.getScaledInstance(width,height,bi.SCALE_SMOOTH); //计算比例 if((bi.getHeight()>height)||(bi.getWidth()>width)){ if(bi.getHeight()>bi.getWidth()){ ratio=(newInteger(height)).doubleValue() /bi.getHeight(); }else{ ratio=(newInteger(width)).doubleValue()/bi.getWidth(); } AffineTransformOpop=newAffineTransformOp(AffineTransform .getScaleInstance(ratio,ratio),null); itemp=op.filter(bi,null); } if(bb){//补白 BufferedImageimage=newBufferedImage(width,height, BufferedImage.TYPE_INT_RGB); Graphics2Dg=image.createGraphics(); g.setColor(Color.white); g.fillRect(0,0,width,height); if(width==itemp.getWidth(null)) g.drawImage(itemp,0,(height-itemp.getHeight(null))/2, itemp.getWidth(null),itemp.getHeight(null), Color.white,null); else g.drawImage(itemp,(width-itemp.getWidth(null))/2,0, itemp.getWidth(null),itemp.getHeight(null), Color.white,null); g.dispose(); itemp=image; } ImageIO.write((BufferedImage)itemp,"JPEG",newFile(result)); }catch(IOExceptione){ e.printStackTrace(); } } /** *图像切割(按指定起点坐标和宽高切割) *@paramsrcImageFile源图像地址 *@paramresult切片后的图像地址 *@paramx目标切片起点坐标X *@paramy目标切片起点坐标Y *@paramwidth目标切片宽度 *@paramheight目标切片高度 */ publicvoidcut(StringsrcImageFile,Stringresult, intx,inty,intwidth,intheight){ try{ //读取源图像 BufferedImagebi=ImageIO.read(newFile(srcImageFile)); intsrcWidth=bi.getHeight();//源图宽度 intsrcHeight=bi.getWidth();//源图高度 if(srcWidth>0&&srcHeight>0){ Imageimage=bi.getScaledInstance(srcWidth,srcHeight, Image.SCALE_DEFAULT); //四个参数分别为图像起点坐标和宽高 //即:CropImageFilter(intx,inty,intwidth,intheight) ImageFiltercropFilter=newCropImageFilter(x,y,width,height); Imageimg=Toolkit.getDefaultToolkit().createImage( newFilteredImageSource(image.getSource(), cropFilter)); BufferedImagetag=newBufferedImage(width,height,BufferedImage.TYPE_INT_RGB); Graphicsg=tag.getGraphics(); g.drawImage(img,0,0,width,height,null);//绘制切割后的图 g.dispose(); //输出为文件 ImageIO.write(tag,"JPEG",newFile(result)); } }catch(Exceptione){ e.printStackTrace(); } } //获得文件名字 publicStringgetFileName(MultipartFilefile,HttpServletRequestrequest,HttpSessionsession){ StringFILE_PATH=session.getServletContext().getRealPath("/")+"upload"; StringfileName=file.getOriginalFilename(); String[]suffixNameArr=fileName.split("\\."); StringsuffixName=suffixNameArr[suffixNameArr.length-1]; StringuserName=SecurityContextHolder.getContext().getAuthentication().getName(); returngetTime()+userName+"."+suffixName; } //文件上传,返回文件路径 publicStringuploadFile(MultipartFilefile,HttpServletRequestrequest,HttpSessionsession)throwsIOException{ StringFILE_PATH=session.getServletContext().getRealPath("/")+"upload"; StringfileName=getFileName(file,request,session); FiletempFile=newFile(FILE_PATH,fileName); if(!tempFile.getParentFile().exists()){ tempFile.getParentFile().mkdir(); } if(!tempFile.exists()){ tempFile.createNewFile(); } file.transferTo(tempFile);//将上传文件写到服务器上指定的文件。 returnFILE_PATH+"\\"+tempFile.getName(); } /*publicstaticFilegetFile(StringfileName){ returnnewFile(FILE_PATH,fileName); }*/ publicStringgetTime(){ Datedate=newDate(); SimpleDateFormatdf=newSimpleDateFormat("yyyyMMddHHmmss");//设置日期格式 StringnowTime=df.format(date).toString(); returnnowTime; } }
这样就将图片要裁剪的图片路径返回页面展示
3.之后就是图片裁剪了,图片裁剪功能我找了好多插件,最后锁定jcrop,也是因为它的demo打动了我(太好看了),之后就是导入文件,在我这里,我在页面接收后台返回来的图片路径之后启用jcrop,也就是openJcrop()方法,这样就可以加载jcrop插件了,具体大家想进一步了解这个裁剪工具,请到官网细细的研究,我就不再做过多的谈论了。
大家注意,在这里有个大坑,真的是大坑,就是重新选择图片的时候,被jcrop加载过的img的src是不能被修改的,这个当初卡了我好长时间,被jcrop加载一次jcrop就会生成一个自己的编辑对象(我自己的理解),这时候就和原来的img没有关系了,直到最后细细研究api才找到了一个方法,唯一的方法就是将这个jcrop销毁,就是jcrop_api.destroy(),这个有很大的学问,我就提示一点,就是将jcrop_api声明为全局变量,下面贴出js代码(和上边的html是在一个文件下):
<scripttype="text/javascript"> $(function(){ varjcrop_api; }); $("#file_upload").change(function(){ $("#msg").text(''); varoFile=$(this)[0].files[0]; //判断上传文件大小 if(oFile.size>1*1024*1024){ $("#msg").text('你选择了太大的文件,请选择一个1M以下的图像文件').css('color','red'); $(this).val(""); return; } //判断类型 varfilepath=$(this).val(); varextStart=filepath.lastIndexOf("."); varext=filepath.substring(extStart,filepath.length).toUpperCase(); if(ext!=".JPEG"&&ext!=".PNG"&&ext!=".JPG"){ $("#msg").text('请选择一个有效的图像文件(jpg,png是允许的)').css('color','red'); $(this).val(""); return; } $("#fileUp").ajaxSubmit({ type:"POST", url:"/file/img/upload", dataType:"json", contentType:"application/json", success:function(parameter){ $("#target2").attr('src','/upload/'+parameter.fileName); $("#filePathInput").val('/upload/'+parameter.fileName); if($("#format").text()=="重新上传"){ jcrop_api.destroy() } $("#format").text("重新上传"); //启动jcrop支持 openJcrop('/upload/'+parameter.fileName); }, error:function(data){ alert("ajax传输发生错误!!!"); } }); }); functionphotoSummit(){ //alert($("#w").val()+","+$("#h").val()+","+$("#x").val()+","+$("#y").val()); //$("#fileUp").attr("action","/file/img/upload").submit(); if($("#w").val()>0&&$("#h").val()>0){ $("#fileUp").ajaxSubmit({ type:"POST", url:"/file/img/cutandscale", dataType:"json", contentType:"application/json", success:function(data){ $("#msg").text('上传头像成功!!!').css('color','red'); //alert($("#filePathInput").val()); window.parent.back($("#filePathInput").val()); }, error:function(data){ alert("ajax传输发生错误!!!"); } }); }else{ $("#msg").text('请用鼠标截取图片').css('color','red'); } } //启动jcrop functionopenJcrop(imgPath){ //启动jcrop支持 varboundx,boundy, xsize=$('#preview-pane.preview-container').width(), ysize=$('#preview-pane.preview-container').height(); $('#target').Jcrop({ minSize:[110,110], onChange:updatePreview, onSelect:updatePreview, aspectRatio:xsize/ysize },function(){ //UsetheAPItogettherealimagesize varbounds=this.getBounds(); boundx=bounds[0]; boundy=bounds[1]; jcrop_api=this; }); jcrop_api.setImage(imgPath); functionupdatePreview(c) { if(parseInt(c.w)>0) { varrx=xsize/c.w; varry=ysize/c.h; $('#preview-pane.preview-containerimg').css({ width:Math.round(rx*boundx)+'px', height:Math.round(ry*boundy)+'px', marginLeft:'-'+Math.round(rx*c.x)+'px', marginTop:'-'+Math.round(ry*c.y)+'px' }); $("#w").val(c.w); $("#h").val(c.h); $("#x").val(c.x); $("#y").val(c.y); } }; } </script>
这样我们就完成了编辑功能,之后我们点击提交就会将w,h,x,y参数传到后台。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。