java中上传头像前剪切和预览

首先说我是个渣渣,写这个供自己以后回顾及一些比我还新的新手借鉴一下,共同学习、共同进步。

百度了好几天,调了3个星期,每天晚上下班回来打开电脑就是调,头都大了,最后还是不负我努力啊,终于正常了点,不过还有点不完美,凑合着用吧!

先说下我的上传头像是个什么形式的:
1、这里有个默认头像


点击默认头像弹出一个框



点击本地图片选择要上传的图片


选择完图片后会立即上传服务器,随即回显,然后你可以在左侧选择剪切区域,右侧预览


选择好要截取的区域后点击保存头像


好了,选择,上传,截取,预览,保存。



进入正题,准备工作:

一、Jcrop插件,没有的话点击这里点击打开链接右下角有下载。

下载完解压,文件夹里有四个js文件



选择这俩个js和一个css,我们会用到。好,准备工作结束。


二、开始写头像上传前预览剪切页面功能,后台会跟着给出。

1、首先说明下,我是在jsp页面开发这个功能的,这个jsp整体结构是一个大form表单里嵌了一个table,然后在table里的一个td里嵌套了一个div,这个头像预览功能就是在这个div里实现。这个div开始是隐藏的,点击默认的头像时弹出及显示,不是一个新页面所以会碰到好多问题。不过如果你单单只是要做个剪切预览功能,你可以把这个div抽离,只把这个div复制出来就好了,只不过我是项目需要。贴代码:

jsp页面:

<form action="" method="post" enctype="multipart/form-data" name="form" id="fom"><td width="40%">
								<div class="bgPhoto">
									<a href="javascript:void(0)" class="cal_decoration"><img id="defauPhoto" title="default" style="width: 120px;height: 120px;" src="${templatedir }/img/defaultPhoto.jpg"/></a>
								</div>
								<div id="light" class="white_content">
									<div style="width: 97.8%;height: 20px;background-color: #B1834C;font-size: 12px;color: white;
									padding-left: 9px;padding-top:2px;float: left;">更换头像
									<a href="javascript:void(0)" id="close" class="cal_decoration">X</a></div>
									<table style="margin-left: 4%">
										<tr>
											<td><a href="javascript:;" class="a-upload">
											    	<input type="file" name="file" id="file" οnchange="checkImgType(this)">本地图片
												</a>
											</td>
											<td style="color: #888888;width: 100%;padding-left: 4%;">预览</td>
										</tr>
										<tr>
											<td id="USERIMAGE"><img id="userimg" style="width: 200px; height: 200px;"/></td>
											<td>
												<div id="preview-pane" style="width: 120px; height: 120px; overflow: hidden; margin-left: 5px;">
													<div class="preview-container">
														<img id="preview"/>
													</div>
												</div>
											</td>
										</tr>
										<tr>
											<td><input type="hidden" id="x" title="截取区相对于图片左上角原点的横坐标"/> 
												<input type="hidden" id="y" title="截取区相对于图片左上角的原点纵坐标"/> 
												<input type="hidden" id="w" title="截取区的宽度"/> 
												<input type="hidden" id="h" title="截取区的高"/>
												<a href="javascript:;" class="a-upload">
													<input type="button" id="photo" οnclick="saveHeadPhoto()"/>保存头像
												</a>
											</td>
										</tr>
									</table>
								</div>
								<div id="fade" class="black_overlay"></div>
							</td>
</form>

对应的css样式 
<style type="text/css">
/*弹框样式*/
.white_content {
	display: none;
	position: absolute;
	top: 14%;
	left: 30%;
	width: 400px;
	/*height: 52%; */
	/*padding: 4px 16px;*/
	background-color: white;
	z-index: 1002;
}
/*弹框样式,背景*/
.black_overlay {
	display: none;
	position: absolute;
	top: 0%;
	left: 0%;
	width: 100%;
	height: 100%;
	background-color: #E2E2E2;
	z-index: 1001;
	-moz-opacity: 0.8;
	opacity: .80;
	filter: alpha(opacity = 80);
}
/*返回的X样式*/
#close {
	color: white;
	margin-left: 82%;
	font-size: 14px;
}


/*没点击之前*/
.cal_decoration:LINK{
	text-decoration: none;/*去除下划线*/
}
/*鼠标点击时*/
.cal_decoration:ACTIVE{
	
}
/*鼠标点击之后*/
.cal_decoration:VISITED{


}
/*鼠标悬停之上*/
.cal_decoration:HOVER {
	
}
/*选择图片按钮*/
.a-upload {
	padding: 4px 10px;
	height: 20px;
	line-height: 20px;
	position: relative;
	cursor: pointer;
	color: #888;
	background: #fafafa;
	border: 1px solid #ddd;
	border-radius: 4px;
	overflow: hidden;
	display: inline-block;
	*display: inline;
	*zoom: 1
}


.a-upload  input {
	position: absolute;
	width: 100px;
	font-size: 100px;
	right: 0;
	top: 0;
	opacity: 0;
	filter: alpha(opacity = 0);
	cursor: pointer
}


.a-upload:hover {
	color: #444;
	background: #eee;
	border-color: #ccc;
	text-decoration: none
}


.a-upload:link {
	text-decoration: none;
}


.bgPhoto {
	background: url("${templatedir }/img/bg.gif") no-repeat left top;
	padding: 7px 12px 12px 7px;
}
/*剪切头像,Jcrop插件里自带的css样式*/
.jcrop-holder #preview-pane {
  display: block;
  position: absolute;
  z-index: 2000;
  top: 35px;
  right: -77%;
  padding: 6px;
  border: 1px rgba(0,0,0,.4) solid;
  background-color: white;


  -webkit-border-radius: 6px;
  -moz-border-radius: 6px;
  border-radius: 6px;


  -webkit-box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
  -moz-box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
  box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
}


#preview-pane .preview-container {
  width: 120px;
  height: 120px;
  overflow: hidden;
}
</style>


2、点击默认头像触发

/*点击默认头像触发*/
$("#defauPhoto").click(function(){
	$("#light").css("display","block");
	$("#fade").css("display","block");
});

3、点击本地图片触发

/*本地相片按钮触发*/
/*检查图片上传类型*/
function checkImgType(obj){//选中图片后预览
	if(""==obj.value){//如果没有选择图片则不提示
		return;
	}
	var imgFile = '';
	var imgFilePath = getImgFullPath(obj);//获取图像路径
	/*图片类型是否正确标识*/
	var tag = true;
	/*通过判断endIndex是否为-1来判断是否选择了文件*/
	var endIndex = imgFilePath.lastIndexOf(".");
	if(endIndex==-1){
		tag = false;
	}
	/*截取图片类型*/
	var imgType = imgFilePath.substring(endIndex+1);
	/*全部转为大写*/
	imgType = imgType.toUpperCase();
	if("GIF"!=imgType && "PNG"!=imgType && "JPG"!=imgType && "BMP"!=imgType){
		tag = false;
	}
	if(!tag){
		alert("上传图片的文件类型必须为: *.gif,*.jpg,*.png,*.bmp,请重新选择!");
		return;
	}
 	var options = { 
		url : '${ctx}/admin/uploadHeadPhoto.do?tempid='+new Date()+Math.random(),
	    type: 'post',
        dataType: 'text',
		success: cutImgCallback,
    };
 	//$.fn.jqLoading();//打开等待层
	$("#fom").ajaxSubmit(options);
}/*上传头像回调*/
function cutImgCallback(data){
	//$.fn.jqLoading("destroy");//关闭等待层
	if("1"==data){
		var imgUrl = document.getElementById("file").files[0];
		var src = window.URL.createObjectURL(imgUrl);
		$("#userimg").attr("src",src);
		$(".jcrop-holder img").attr("src",src);
		//头像剪切函数
		cutImg(src);
	}else{
		alert("网络连接出现问题,稍后请重试!");
	}
}
/*剪切头像,Jcrop插件,官网有教程*/
function cutImg(src){
		$("#userimg").Jcrop({
		onChange : showPreview,
		onSelect : showPreview,
		aspectRatio : xsize / ysize
	}, function() {
		var bounds = this.getBounds();
		boundx = bounds[0];
		boundy = bounds[1];
		jcrop_api = this;
		$preview.appendTo(jcrop_api.ui.holder);
		$("#preview").attr("src",src);//在插件加载完成后,重新给预览区赋值解决二次进入预览区因缓存问题图片还是上次的。之前预览区第二次选择图片就是上次的图片,找了好久好久,最后把它重新赋值就好了,我觉得是缓存问题

	});
}/*选择框改变是执行此函数*/
function showPreview(c) {
	if (parseInt(c.w) > 0) {
		var rx = xsize / c.w;
		var ry = ysize / c.h;
		$("#x").val(Math.round(rx * c.x));
		$("#y").val(Math.round(ry * c.y));
		$("#w").val(Math.round(rx * boundx));
		$("#h").val(Math.round(ry * boundy));
		$pimg.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'
		});
	}
}

 
 
/*获取图片全路径*/
function getImgFullPath(obj){
	if(obj){
		//ie
		if(window.navigator.userAgent.indexOf("MSIE")>=1){
			obj.select();
			return document.selection.createRange().text();
		}else if(window.navigator.userAgent.indexOf("Firefox")>=1){
		//firefox
			if(obj.files){
				return obj.files.item(0).getAsDataURL();
			}
			return obj.value;
		}
		return obj.value;
	}
}


4、选择好截取区域后点击保存头像触发 

/*保存头像按钮触发*/
function saveHeadPhoto(){
	var fileImage = $("#file").val();
	if(""==fileImage){
		alert("请选择上传图片!");
		return;
	}
	var w = $("#w").val();
	var h = $("#h").val();
	if(w==0||h==0){
		alert("请选择所要裁剪的头像区域!");
		return;
	}
	var url = "${ctx}/admin/uploadImageCut.do";
	var type = "text";
	var data = {
		"x": $("#x").val(),
		"y": $("#y").val(),
		"w1": xsize,//预览区宽度
		"h1": ysize,//预览区高度
		"w": $("#w").val(),
		"h": $("#h").val(),
	};
	//$.fn.jqLoading({text:'正在保存,请稍后...'});//打开等待层
	$.post(url,data,ctuImageCallback,type);
}
/*保存头像回调函数*/
function ctuImageCallback(data){ 
	//var jsonData = eval("("+data+")");//最简单一种字符串json转为json对象
	var jsonData = JSON.parse(data);//第二种字符串json转为json对象
	//$.fn.jqLoading("destroy");//关闭等待层
	if("1"==jsonData.flag){
		destroyImageCut();//请求成功即销毁头像截取及预览以便下次选择头像初始化为未选择
		//$("#defauPhoto").attr("title","userImage");//头像上传成功改变title标识确定用户是否上传过头像
		var src = "${ctx}/"+jsonData.url;//保存后立即回显图片的路径
		$("#defauPhoto").attr("src",src);
	}else{
		alert("保存失败!");
	}
}

需要说明的是 这两个参数。这俩个参数是预览区


的宽度和高度,不然截取的图片大小不对啊,按照Jcrop官网和网上的博客都是后台截图用左侧截取框的宽度和高度,但是跟我的情况不一样,找了好久才找到原因。

5、点击X或者保存头像后要销毁Jcrop

/*点击X触发*/
$("#close").click(function(){
	destroyImageCut();//销毁头像截取及预览以便下次选择头像初始化为未选择
});
function destroyImageCut(){
	$("#file").val("");//清除选择的图片文件
	if(jcrop_api){
		jcrop_api.destroy();//销毁
	}
	//重新写入img标签,防止第二次进入选择图片时,Jcrop插件把选择的图片宽度赋给img宽度
	$("#USERIMAGE").html("<img id='userimg' style='width: 200px; height: 200px;'/>");
	$("#light").css("display","none");
	$("#fade").css("display","none");
}

 

这样前台的代码就没了。下面是后台的代码。

二、JAVA后台代码:

1、uploadHeadPhoto.do的方法,我用的是springMVC。首先定义几个全局变量

public static final String IMGROOT = "/uploads/admin/";//图片要保存的文件位置
	//重写servletConfig方法,得到servletConfig,因为smartUpload要用到这个参数
	private ServletConfig servletConfig;
	@Override
	public void setServletConfig(ServletConfig arg0) { 
		this.servletConfig = arg0;
	}
	


//原显示图片路径
String oldImgPath = null;//图片后缀String imgFileExt1 = null;String imgRoot = null;Integer width1 = 0;Integer height1 = 0;

 

        /**
	 * 头像上传
	 */
	@RequestMapping("/uploadHeadPhoto")
	public void uploadHeadPhoto(HttpServletRequest request,HttpServletResponse response) throws IOException{
		String uploadPath = request.getSession().getServletContext().getRealPath("/")+IMGROOT;
		/*检查是否有存放上传的图片文件夹*/
		CommonUtil.checkDirs(uploadPath);
		/*图片后缀名*/
		String imgFileExt = "";
		/*图片上传的相对路径*/
		String imgUploadPath = "";
		String imgWebAppPath = "";
		/*图片名称:当前日期*/
		String imgFileId = DateUtil.DateToStr(new Date(), "yyyyMMddhhmmss");
		//图片初始化高度与宽度
		//String width = null;
		//String height = null;
		
		int imgWidth = 0;
		int imgHeight = 0;		
		try {
			com.jspsmart.upload.SmartUpload smartUpload = new com.jspsmart.upload.SmartUpload();
			smartUpload.initialize(servletConfig, request, response);
			smartUpload.upload();
			
			//文件个数
			int fileCounts =  smartUpload.getFiles().getCount();
			
			for (int i = 0; i <fileCounts; i++) {
				com.jspsmart.upload.File myFile = smartUpload.getFiles().getFile(i);
				
				if (!myFile.isMissing()) {
					
					imgFileExt = myFile.getFileExt();
					//组装图片名称
					imgFileId += "_" + i + "_" + System.currentTimeMillis() + "." + imgFileExt;
					
					//图片生成路径
					imgWebAppPath = uploadPath + imgFileId;
					
					//生成图片文件
					myFile.saveAs(imgWebAppPath);
					//图片的相对路径
					imgUploadPath = IMGROOT + imgFileId;
					
					//检查图片大小
					BufferedImage src = ImageIO.read(new File(imgWebAppPath)); // 读入文件						 
					//int imgSrcWidth = src.getWidth(); // 得到源图宽							 
					imgHeight = src.getHeight();
					//按照图片的设置大小生成
					ImageCutUtil.scale(imgWebAppPath, imgWebAppPath,imgWidth,imgHeight);
					File f = new File(imgWebAppPath);								
					if(f.exists()){						
						logger.info("创建"+imgWidth+"*"+imgHeight+"图片成功");
					}				
					oldImgPath=imgUploadPath;
					imgFileExt1=imgFileExt;
					imgRoot=IMGROOT;
					width1=imgWidth;
					height1=imgHeight;
					request.setCharacterEncoding("UTF-8");
					response.setContentType("text/html;charset=UTF-8");
					response.getWriter().print("1");
				}
				
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}	<span style="white-space:pre">																		</span>/**
	 * 用户剪切后点击保存头像调用方法
	 * @param  x 截取x坐标
	 * @param  y 截取y坐标
	 * @param  w1 截取宽度(这里是预览区宽度)
	 * @param  h1 截取高度(这里是预览区高度)
	 * @param  w 缩放宽度
	 * @param  h 缩放高度
	 * @throws IOException 
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@RequestMapping("/uploadImageCut")
	@ResponseBody
	public void ImageCut(HttpServletRequest request,HttpServletResponse response) throws IOException{
		try {
			logger.info("x:"+request.getParameter("x")+",y:"+request.getParameter("y")+
					",w1:"+request.getParameter("w1")+",h1:"+request.getParameter("h1")+
					",w:"+request.getParameter("w")+",h:"+request.getParameter("h"));
			// 用户经过剪辑后的图片的大小
			Integer x = Integer.parseInt(request.getParameter("x"));
			Integer y = Integer.parseInt(request.getParameter("y"));
			Integer w1 = Integer.parseInt(request.getParameter("w1"));
			Integer h1 = Integer.parseInt(request.getParameter("h1"));
			Integer w = Integer.parseInt(request.getParameter("w"));
			Integer h = Integer.parseInt(request.getParameter("h"));
			
			//WEB应用程序根路径
			String rootPath  = request.getSession().getServletContext().getRealPath("/");
			/*图片名称:以当前日期*/
			String imgFileId = DateUtil.DateToStr(new Date(), "yyyyMMddhhmmss");
			String imgName = imgRoot + imgFileId + System.currentTimeMillis() +  "." + imgFileExt1;
			/*组装图片真实名称*/
			String createImgPath = rootPath + imgName;
			/*之前上传的图片路径*/
			rootPath += oldImgPath;
			logger.info("原图片路径: " + rootPath + ",新图片路径: " + createImgPath);
			
			/*进行剪切图片操作*/
			ImageCutUtil.abscut(rootPath, createImgPath, x, y, w1, h1, w, h);
			File file = new File(createImgPath);
			if(file.exists()){
				logger.info("剪切图片大小: "+w1+"*"+h1+"图片成功!");
			}
			
			Map jsonMap = new HashMap();
			jsonMap.put("url", imgName);
			jsonMap.put("flag", "1");
			//photoImg = createImgPath;//头像全路径保存到数据库
			JSONObject jsonObject = JSONObject.fromObject(jsonMap);
			request.setCharacterEncoding("UTF-8");
			response.setContentType("text/html;charset=UTF-8");
			response.getWriter().print(jsonObject.toString());//上传成功!
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
	}	
       /**
	 * 缩放后裁剪图片方法
	 * 
	 * @param srcImageFile  源图像地址
	 * @param dirImageFile  新图像地址
	 * @param x  目标切片起点x坐标
	 * @param y  目标切片起点y坐标
	 * @param destWidth  目标切片宽度
	 * @param destHeight  目标切片高度
	 * @param finalWidth   缩放宽度            
	 * @param finalHeight  缩放高度        
	 */
	public static void abscut(String srcImageFile, String dirImageFile, int x,
			int y, int destWidth, int destHeight,int finalWidth,int finalHeight) {
		try {
			Image img;
			ImageFilter cropFilter;
			//FileInputStream is = null;
			//ImageInputStream iis = null;
			// 读取源图像
			BufferedImage bi = ImageIO.read(new File(srcImageFile));
			int srcWidth = bi.getWidth(); // 源图宽度
			int srcHeight = bi.getHeight(); // 源图高度
			System.out.println("srcWidth:"+srcWidth+",srcHeight:"+srcHeight);
			if (srcWidth >= destWidth && srcHeight >= destHeight) {//保证源图高度大于截取高度
				Image image = bi.getScaledInstance(finalWidth, finalHeight, bi.SCALE_SMOOTH);//获取缩放后的图片大小
				// 四个参数分别为图像起点坐标和宽高
				// 即: CropImageFilter(int x,int y,int width,int height)
				cropFilter = new CropImageFilter(x, y, destWidth, destHeight);
				img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(image.getSource(), cropFilter));
				BufferedImage tag = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_RGB);
				Graphics g = tag.getGraphics();
				g.drawImage(img, 0, 0, null); // 绘制缩放后的图
				g.dispose();
				// 输出为文件
				ImageIO.write(tag, "PNG", new File(dirImageFile));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}<span style="white-space:pre">																		</span>         /**
	 * 判断目录是否存在,不存在就新建,多级父目录
	 * @param path
	 */
	public static void checkDirs(String path) {		
		 File file = new File(path);
		 if(!file.exists()){
			 file.mkdirs();
		 }
	}
差点忘了一个上传组件smartUpload, 

 

类太多了,不好贴,网上搜,很多的,引用的时候三五行代码,在头像上传那个类里(uploadHeadPhoto)






  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值