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参数传到后台。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。