最近在做项目时候需要一个头像长传功能,但是现在照片动不动就几兆的,都是流量的浪费。
我只是简单想要上传一个头像而已。。。
经过几天发愤图强。。总算是略有所获。。
基本思路:
1、html部分,图片剪辑功能。主要就是整个图片选择一块,可以选取某一块,调整大小等
2、将选择的图片画在canvas中。当点击上传时候,将图片转化成base64格式,传给后台jsp页面
3、jsp将base64的格式的图片转化成文件格式存在服务器里(当然,直接将字符串存入数据库也可以)
效果如下:
生成图片:
html代码如下:
<!doctype html>
<html>
<head>
<style type="text/css">
body{background:#888;}
#box{left:200px;top:100px;position:absolute;}
#imgBox{position:absolute;left:0px;top:0px;}
#imgBox img{opacity:0.5;}
#clipBox img{clip:rect(0px,200px,200px,0px);position:absolute;}
#clipDiv{position:absolute;left:0px;top:0px;width:200px;height:200px;border:1px solid #fff;cursor:move;}
#clipDiv div{position:absolute;width:8px;height:8px;background:#FFF;margin-left:-4px;margin-top:-4px;}
#clipDiv :nth-child(1){left:0px;top:0px;cursor:nw-resize;}
#clipDiv :nth-child(2){left:50%;top:0px;cursor:n-resize;}
#clipDiv :nth-child(3){left:100%;top:0px;cursor:ne-resize;}
#clipDiv :nth-child(4){left:100%;top:50%;cursor:e-resize;}
#clipDiv :nth-child(5){left:100%;top:100%;cursor:se-resize;}
#clipDiv :nth-child(6){left:50%;top:100%;cursor:s-resize;}
#clipDiv :nth-child(7){left:0px;top:100%;cursor:sw-resize;}
#clipDiv :nth-child(8){left:0px;top:50%;cursor:w-resize;}
#photoBox{position:absolute;left:900px;top:100px;width:200px;height:200px;}
#photoBox #photo{position:absolute;}
#submit{position:absolute;left:200px;top:40px;width:100px;height:40px;line-height:40px;text-align:center;border:solid 1px #000;cursor:pointer;border-radius:4px;}
#res{position:absolute;left:320px;top:40px;width:500px;height:40px;line-height:40px;text-align:center;border:solid 1px #000;cursor:pointer;border-radius:4px;}
</style>
</head>
<body>
<div id="submit">submit</div>
<div id="res"></div>
<div id="box">
<div id="imgBox"></div>
<div id="clipBox"></div>
<div id="clipDiv"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>
</div>
<div id="photoBox"><canvas id="photo" width='200' height='200' style='border:solid #000 1px;'></canvas></div>
<script>
var CLIP_WIDTH = 200 ;//头像宽度
var CLIP_HEIGHT = 200 ;//头像高度
var maxWidth = 0;//引用图片宽度
var maxHeight = 0 ;//引用图片高度 var box = $('clipDiv') ;//选取框层
var clipImg = $('clipBox') ; //选取图片层
var canvas = $('photo') ;//canvas层
var photo = canvas.getContext('2d') ; var elem = -1 ; //当前选择元素
var boxLeft = 0 ;
var boxTop = 0 ;
var boxWidth = 0 ;
var boxHeight = 0 ;
var mouseX = 0 ;
var mouseY = 0 ; var img = new Image() ;
img.src = '1.jpg' ;//原始图片
img.onload = funInit ;
$('submit').onclick = funUpdateImg ; //图片剪辑 for(var i = 0 ; i < box.childNodes.length ; i ++){
box.childNodes[i].index = i ;
box.childNodes[i].onmousedown = function(e){
elem = this.index ;
mouseX = e.clientX ;
mouseY = e.clientY ;
boxWidth = box.offsetWidth-2 ;
boxHeight = box.offsetHeight-2 ;
boxLeft = box.offsetLeft ;
boxTop = box.offsetTop ;
e.cancelBubble = true;
}
}
box.onmousedown = function(e){
elem = 8 ;
mouseX = e.clientX ;
mouseY = e.clientY ;
boxWidth = box.offsetWidth-2 ;
boxHeight = box.offsetHeight-2 ;
boxLeft = box.offsetLeft ;
boxTop = box.offsetTop ;
} window.onmousemove = function(e){
if(elem == -1)return ;
var x = e.clientX ;
var y = e.clientY ;
var curLeft = boxLeft ;
var curTop = boxTop ;
var curWidth = boxWidth ;
var curHeight = boxHeight ;
switch(elem){
case 0:
curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,boxLeft+boxWidth)) ;
curTop = Math.max(0,Math.min(boxTop + y - mouseY,boxTop+boxHeight)) ;
curWidth = boxLeft+boxWidth-curLeft ;
curHeight = boxTop +boxHeight-curTop ;
break;
case 1:
curTop = Math.max(0,Math.min(boxTop + y - mouseY,boxTop+boxHeight)) ;
curHeight = boxTop +boxHeight-curTop ;
break;
case 2:
curTop = Math.max(0,Math.min(boxTop + y - mouseY,boxTop+boxHeight)) ;
curHeight = boxTop +boxHeight-curTop ;
curWidth = Math.max(0,Math.min(boxWidth+x-mouseX,maxWidth));
break;
case 3:
curWidth = Math.max(0,Math.min(boxWidth+x-mouseX,maxWidth));
break;
case 4:
curWidth = Math.max(0,Math.min(boxWidth+x-mouseX,maxWidth));
curHeight = Math.max(0,Math.min(boxHeight+y-mouseY,maxHeight));
break;
case 5:
curHeight = Math.max(0,Math.min(boxHeight+y-mouseY,maxHeight));
break;
case 6:
curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,boxLeft+boxWidth)) ;
curWidth = boxLeft+boxWidth-curLeft ;
curHeight = Math.max(0,Math.min(boxHeight+y-mouseY,maxHeight));
break;
case 7:
curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,boxLeft+boxWidth)) ;
curWidth = boxLeft+boxWidth-curLeft ;
break;
case 8:
curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,maxWidth-boxWidth)) ;
curTop = Math.max(0,Math.min(boxTop + y - mouseY,maxHeight-boxHeight)) ;
break;
}
box.style.left = curLeft + 'px' ;
box.style.top = curTop + 'px' ;
box.style.width = curWidth + 'px' ;
box.style.height = curHeight + 'px' ;
clipImg.childNodes[0].style.clip = "rect("+curTop+"px,"+(curLeft+curWidth)+"px,"+(curTop+curHeight)+"px,"+(curLeft)+"px)" ;
showPhoto(curLeft,curTop,curWidth,curHeight) ;
}
window.onmouseup = function(){
elem = -1 ;
} //将选中的图片画在canvas上
function showPhoto(left,top,width,height){
photo.clearRect(0,0,CLIP_WIDTH,CLIP_HEIGHT) ;
photo.drawImage(img,-left*CLIP_WIDTH/width,-top*CLIP_HEIGHT/height,maxWidth*CLIP_WIDTH/width,maxHeight*CLIP_HEIGHT/height);
}
//获取base64格式的png图片内容
function funGetImg(){
var data = canvas.toDataURL("image/png") ;
data = data.replace(/\+/g,"#") ;//后台java代码中加号出问题
return data ;
}
//post方式将内容传给后台
function ajaxSendImg(str,callback){
var xmlhttp = new XMLHttpRequest() ;
xmlhttp.open("post","base64toimg.jsp",false);
xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xmlhttp.send(str);
callback.call(null,xmlhttp.responseText) ;
} function funUpdateImg(){
var data = funGetImg() ;
var url = "imgStr="+data.substring(22) ;
ajaxSendImg(url,log);
} function $(id){
return document.getElementById(id) ;
} function log(){
$('res').innerHTML = arguments[0] ;
} function funInit(){
maxWidth = this.width ;
maxHeight= this.height ;
$('clipBox').appendChild(img) ;
var newImg = new Image() ;
newImg.src = this.src ;
$('imgBox').appendChild(newImg);
showPhoto(0,0,CLIP_WIDTH,CLIP_HEIGHT);
}
</script>
</body>
</html>
jsp代码:
<!doctype html>
<html>
<head>
<style type="text/css">
body{background:#888;}
#box{left:200px;top:100px;position:absolute;}
#imgBox{position:absolute;left:0px;top:0px;}
#imgBox img{opacity:0.5;}
#clipBox img{clip:rect(0px,200px,200px,0px);position:absolute;}
#clipDiv{position:absolute;left:0px;top:0px;width:200px;height:200px;border:1px solid #fff;cursor:move;}
#clipDiv div{position:absolute;width:8px;height:8px;background:#FFF;margin-left:-4px;margin-top:-4px;}
#clipDiv :nth-child(1){left:0px;top:0px;cursor:nw-resize;}
#clipDiv :nth-child(2){left:50%;top:0px;cursor:n-resize;}
#clipDiv :nth-child(3){left:100%;top:0px;cursor:ne-resize;}
#clipDiv :nth-child(4){left:100%;top:50%;cursor:e-resize;}
#clipDiv :nth-child(5){left:100%;top:100%;cursor:se-resize;}
#clipDiv :nth-child(6){left:50%;top:100%;cursor:s-resize;}
#clipDiv :nth-child(7){left:0px;top:100%;cursor:sw-resize;}
#clipDiv :nth-child(8){left:0px;top:50%;cursor:w-resize;}
#photoBox{position:absolute;left:900px;top:100px;width:200px;height:200px;}
#photoBox #photo{position:absolute;}
#submit{position:absolute;left:200px;top:40px;width:100px;height:40px;line-height:40px;text-align:center;border:solid 1px #000;cursor:pointer;border-radius:4px;}
#res{position:absolute;left:320px;top:40px;width:500px;height:40px;line-height:40px;text-align:center;border:solid 1px #000;cursor:pointer;border-radius:4px;}
</style>
</head>
<body>
<div id="submit">submit</div>
<div id="res"></div>
<div id="box">
<div id="imgBox"></div>
<div id="clipBox"></div>
<div id="clipDiv"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>
</div>
<div id="photoBox"><canvas id="photo" width='200' height='200' style='border:solid #000 1px;'></canvas></div>
<script>
var CLIP_WIDTH = 200 ;//头像宽度
var CLIP_HEIGHT = 200 ;//头像高度
var maxWidth = 0;//引用图片宽度
var maxHeight = 0 ;//引用图片高度 var box = $('clipDiv') ;//选取框层
var clipImg = $('clipBox') ; //选取图片层
var canvas = $('photo') ;//canvas层
var photo = canvas.getContext('2d') ; var elem = -1 ; //当前选择元素
var boxLeft = 0 ;
var boxTop = 0 ;
var boxWidth = 0 ;
var boxHeight = 0 ;
var mouseX = 0 ;
var mouseY = 0 ; var img = new Image() ;
img.src = '1.jpg' ;//原始图片
img.onload = funInit ;
$('submit').onclick = funUpdateImg ; //图片剪辑 for(var i = 0 ; i < box.childNodes.length ; i ++){
box.childNodes[i].index = i ;
box.childNodes[i].onmousedown = function(e){
elem = this.index ;
mouseX = e.clientX ;
mouseY = e.clientY ;
boxWidth = box.offsetWidth-2 ;
boxHeight = box.offsetHeight-2 ;
boxLeft = box.offsetLeft ;
boxTop = box.offsetTop ;
e.cancelBubble = true;
}
}
box.onmousedown = function(e){
elem = 8 ;
mouseX = e.clientX ;
mouseY = e.clientY ;
boxWidth = box.offsetWidth-2 ;
boxHeight = box.offsetHeight-2 ;
boxLeft = box.offsetLeft ;
boxTop = box.offsetTop ;
} window.onmousemove = function(e){
if(elem == -1)return ;
var x = e.clientX ;
var y = e.clientY ;
var curLeft = boxLeft ;
var curTop = boxTop ;
var curWidth = boxWidth ;
var curHeight = boxHeight ;
switch(elem){
case 0:
curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,boxLeft+boxWidth)) ;
curTop = Math.max(0,Math.min(boxTop + y - mouseY,boxTop+boxHeight)) ;
curWidth = boxLeft+boxWidth-curLeft ;
curHeight = boxTop +boxHeight-curTop ;
break;
case 1:
curTop = Math.max(0,Math.min(boxTop + y - mouseY,boxTop+boxHeight)) ;
curHeight = boxTop +boxHeight-curTop ;
break;
case 2:
curTop = Math.max(0,Math.min(boxTop + y - mouseY,boxTop+boxHeight)) ;
curHeight = boxTop +boxHeight-curTop ;
curWidth = Math.max(0,Math.min(boxWidth+x-mouseX,maxWidth));
break;
case 3:
curWidth = Math.max(0,Math.min(boxWidth+x-mouseX,maxWidth));
break;
case 4:
curWidth = Math.max(0,Math.min(boxWidth+x-mouseX,maxWidth));
curHeight = Math.max(0,Math.min(boxHeight+y-mouseY,maxHeight));
break;
case 5:
curHeight = Math.max(0,Math.min(boxHeight+y-mouseY,maxHeight));
break;
case 6:
curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,boxLeft+boxWidth)) ;
curWidth = boxLeft+boxWidth-curLeft ;
curHeight = Math.max(0,Math.min(boxHeight+y-mouseY,maxHeight));
break;
case 7:
curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,boxLeft+boxWidth)) ;
curWidth = boxLeft+boxWidth-curLeft ;
break;
case 8:
curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,maxWidth-boxWidth)) ;
curTop = Math.max(0,Math.min(boxTop + y - mouseY,maxHeight-boxHeight)) ;
break;
}
box.style.left = curLeft + 'px' ;
box.style.top = curTop + 'px' ;
box.style.width = curWidth + 'px' ;
box.style.height = curHeight + 'px' ;
clipImg.childNodes[0].style.clip = "rect("+curTop+"px,"+(curLeft+curWidth)+"px,"+(curTop+curHeight)+"px,"+(curLeft)+"px)" ;
showPhoto(curLeft,curTop,curWidth,curHeight) ;
}
window.onmouseup = function(){
elem = -1 ;
} //将选中的图片画在canvas上
function showPhoto(left,top,width,height){
photo.clearRect(0,0,CLIP_WIDTH,CLIP_HEIGHT) ;
photo.drawImage(img,-left*CLIP_WIDTH/width,-top*CLIP_HEIGHT/height,maxWidth*CLIP_WIDTH/width,maxHeight*CLIP_HEIGHT/height);
}
//获取base64格式的png图片内容
function funGetImg(){
var data = canvas.toDataURL("image/png") ;
data = data.replace(/\+/g,"#") ;//后台java代码中加号出问题
return data ;
}
//post方式将内容传给后台
function ajaxSendImg(str,callback){
var xmlhttp = new XMLHttpRequest() ;
xmlhttp.open("post","base64toimg.jsp",false);
xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xmlhttp.send(str);
callback.call(null,xmlhttp.responseText) ;
} function funUpdateImg(){
var data = funGetImg() ;
var url = "imgStr="+data.substring(22) ;
ajaxSendImg(url,log);
} function $(id){
return document.getElementById(id) ;
} function log(){
$('res').innerHTML = arguments[0] ;
} function funInit(){
maxWidth = this.width ;
maxHeight= this.height ;
$('clipBox').appendChild(img) ;
var newImg = new Image() ;
newImg.src = this.src ;
$('imgBox').appendChild(newImg);
showPhoto(0,0,CLIP_WIDTH,CLIP_HEIGHT);
}
</script>
</body>
</html
<%@page contentType="text/html;charset=utf-8"%>
<%@page import="java.io.*,sun.misc.BASE64Decoder,sun.misc.BASE64Encoder"%>
<%
String imgStr = request.getParameter("imgStr");
imgStr = imgStr.replaceAll("#","+");
BASE64Decoder decoder = new BASE64Decoder();
try{
byte[] b = decoder.decodeBuffer(imgStr);
String relPath = application.getRealPath("/") ;
String path = "/upload/photo.png" ;
File f = new File(relPath + path);
OutputStream os = new FileOutputStream(f);
os.write(b);
os.flush();
os.close();
out.println(path);
}
catch (Exception e)
{
out.println("error");
}
%>
将base64图片内容传给jsp时候。老是会出错。发现是因为“+”传过去就解析成其他符号了。。一直想不明白。。
只能暂时将“+”缓存“#”,到jsp之后在repalce过来,如果有人知道是怎么回事,希望告知下。。
欢迎讨论,转载请注明出处。谢谢!