最近在做项目时候需要一个头像长传功能,但是现在照片动不动就几兆的,都是流量的浪费。
我只是简单想要上传一个头像而已。。。
经过几天发愤图强。。总算是略有所获。。
基本思路:
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代码:
1 <!doctype html> 2 <html> 3 <head> 4 <style type="text/css"> 5 body{background:#888;} 6 #box{left:200px;top:100px;position:absolute;} 7 #imgBox{position:absolute;left:0px;top:0px;} 8 #imgBox img{opacity:0.5;} 9 #clipBox img{clip:rect(0px,200px,200px,0px);position:absolute;} 10 #clipDiv{position:absolute;left:0px;top:0px;width:200px;height:200px;border:1px solid #fff;cursor:move;} 11 #clipDiv div{position:absolute;width:8px;height:8px;background:#FFF;margin-left:-4px;margin-top:-4px;} 12 #clipDiv :nth-child(1){left:0px;top:0px;cursor:nw-resize;} 13 #clipDiv :nth-child(2){left:50%;top:0px;cursor:n-resize;} 14 #clipDiv :nth-child(3){left:100%;top:0px;cursor:ne-resize;} 15 #clipDiv :nth-child(4){left:100%;top:50%;cursor:e-resize;} 16 #clipDiv :nth-child(5){left:100%;top:100%;cursor:se-resize;} 17 #clipDiv :nth-child(6){left:50%;top:100%;cursor:s-resize;} 18 #clipDiv :nth-child(7){left:0px;top:100%;cursor:sw-resize;} 19 #clipDiv :nth-child(8){left:0px;top:50%;cursor:w-resize;} 20 #photoBox{position:absolute;left:900px;top:100px;width:200px;height:200px;} 21 #photoBox #photo{position:absolute;} 22 #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;} 23 #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;} 24 </style> 25 </head> 26 <body> 27 <div id="submit">submit</div> 28 <div id="res"></div> 29 <div id="box"> 30 <div id="imgBox"></div> 31 <div id="clipBox"></div> 32 <div id="clipDiv"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div> 33 </div> 34 <div id="photoBox"><canvas id="photo" width='200' height='200' style='border:solid #000 1px;'></canvas></div> 35 <script> 36 var CLIP_WIDTH = 200 ;//头像宽度 37 var CLIP_HEIGHT = 200 ;//头像高度 38 var maxWidth = 0;//引用图片宽度 39 var maxHeight = 0 ;//引用图片高度 40 41 var box = $('clipDiv') ;//选取框层 42 var clipImg = $('clipBox') ; //选取图片层 43 var canvas = $('photo') ;//canvas层 44 var photo = canvas.getContext('2d') ; 45 46 var elem = -1 ; //当前选择元素 47 var boxLeft = 0 ; 48 var boxTop = 0 ; 49 var boxWidth = 0 ; 50 var boxHeight = 0 ; 51 var mouseX = 0 ; 52 var mouseY = 0 ; 53 54 var img = new Image() ; 55 img.src = '1.jpg' ;//原始图片 56 img.onload = funInit ; 57 $('submit').onclick = funUpdateImg ; 58 59 //图片剪辑 60 61 for(var i = 0 ; i < box.childNodes.length ; i ++){ 62 box.childNodes[i].index = i ; 63 box.childNodes[i].onmousedown = function(e){ 64 elem = this.index ; 65 mouseX = e.clientX ; 66 mouseY = e.clientY ; 67 boxWidth = box.offsetWidth-2 ; 68 boxHeight = box.offsetHeight-2 ; 69 boxLeft = box.offsetLeft ; 70 boxTop = box.offsetTop ; 71 e.cancelBubble = true; 72 } 73 } 74 box.onmousedown = function(e){ 75 elem = 8 ; 76 mouseX = e.clientX ; 77 mouseY = e.clientY ; 78 boxWidth = box.offsetWidth-2 ; 79 boxHeight = box.offsetHeight-2 ; 80 boxLeft = box.offsetLeft ; 81 boxTop = box.offsetTop ; 82 } 83 84 window.onmousemove = function(e){ 85 if(elem == -1)return ; 86 var x = e.clientX ; 87 var y = e.clientY ; 88 var curLeft = boxLeft ; 89 var curTop = boxTop ; 90 var curWidth = boxWidth ; 91 var curHeight = boxHeight ; 92 switch(elem){ 93 case 0: 94 curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,boxLeft+boxWidth)) ; 95 curTop = Math.max(0,Math.min(boxTop + y - mouseY,boxTop+boxHeight)) ; 96 curWidth = boxLeft+boxWidth-curLeft ; 97 curHeight = boxTop +boxHeight-curTop ; 98 break; 99 case 1: 100 curTop = Math.max(0,Math.min(boxTop + y - mouseY,boxTop+boxHeight)) ; 101 curHeight = boxTop +boxHeight-curTop ; 102 break; 103 case 2: 104 curTop = Math.max(0,Math.min(boxTop + y - mouseY,boxTop+boxHeight)) ; 105 curHeight = boxTop +boxHeight-curTop ; 106 curWidth = Math.max(0,Math.min(boxWidth+x-mouseX,maxWidth)); 107 break; 108 case 3: 109 curWidth = Math.max(0,Math.min(boxWidth+x-mouseX,maxWidth)); 110 break; 111 case 4: 112 curWidth = Math.max(0,Math.min(boxWidth+x-mouseX,maxWidth)); 113 curHeight = Math.max(0,Math.min(boxHeight+y-mouseY,maxHeight)); 114 break; 115 case 5: 116 curHeight = Math.max(0,Math.min(boxHeight+y-mouseY,maxHeight)); 117 break; 118 case 6: 119 curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,boxLeft+boxWidth)) ; 120 curWidth = boxLeft+boxWidth-curLeft ; 121 curHeight = Math.max(0,Math.min(boxHeight+y-mouseY,maxHeight)); 122 break; 123 case 7: 124 curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,boxLeft+boxWidth)) ; 125 curWidth = boxLeft+boxWidth-curLeft ; 126 break; 127 case 8: 128 curLeft = Math.max(0,Math.min(boxLeft + x - mouseX,maxWidth-boxWidth)) ; 129 curTop = Math.max(0,Math.min(boxTop + y - mouseY,maxHeight-boxHeight)) ; 130 break; 131 } 132 box.style.left = curLeft + 'px' ; 133 box.style.top = curTop + 'px' ; 134 box.style.width = curWidth + 'px' ; 135 box.style.height = curHeight + 'px' ; 136 clipImg.childNodes[0].style.clip = "rect("+curTop+"px,"+(curLeft+curWidth)+"px,"+(curTop+curHeight)+"px,"+(curLeft)+"px)" ; 137 showPhoto(curLeft,curTop,curWidth,curHeight) ; 138 } 139 window.onmouseup = function(){ 140 elem = -1 ; 141 } 142 143 //将选中的图片画在canvas上 144 function showPhoto(left,top,width,height){ 145 photo.clearRect(0,0,CLIP_WIDTH,CLIP_HEIGHT) ; 146 photo.drawImage(img,-left*CLIP_WIDTH/width,-top*CLIP_HEIGHT/height,maxWidth*CLIP_WIDTH/width,maxHeight*CLIP_HEIGHT/height); 147 } 148 //获取base64格式的png图片内容 149 function funGetImg(){ 150 var data = canvas.toDataURL("image/png") ; 151 data = data.replace(/+/g,"#") ;//后台java代码中加号出问题 152 return data ; 153 } 154 //post方式将内容传给后台 155 function ajaxSendImg(str,callback){ 156 var xmlhttp = new XMLHttpRequest() ; 157 xmlhttp.open("post","base64toimg.jsp",false); 158 xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); 159 xmlhttp.send(str); 160 callback.call(null,xmlhttp.responseText) ; 161 } 162 163 function funUpdateImg(){ 164 var data = funGetImg() ; 165 var url = "imgStr="+data.substring(22) ; 166 ajaxSendImg(url,log); 167 } 168 169 function $(id){ 170 return document.getElementById(id) ; 171 } 172 173 function log(){ 174 $('res').innerHTML = arguments[0] ; 175 } 176 177 function funInit(){ 178 maxWidth = this.width ; 179 maxHeight= this.height ; 180 $('clipBox').appendChild(img) ; 181 var newImg = new Image() ; 182 newImg.src = this.src ; 183 $('imgBox').appendChild(newImg); 184 showPhoto(0,0,CLIP_WIDTH,CLIP_HEIGHT); 185 } 186 </script> 187 </body> 188 </html
1 <%@page contentType="text/html;charset=utf-8"%> 2 <%@page import="java.io.*,sun.misc.BASE64Decoder,sun.misc.BASE64Encoder"%> 3 <% 4 String imgStr = request.getParameter("imgStr"); 5 imgStr = imgStr.replaceAll("#","+"); 6 BASE64Decoder decoder = new BASE64Decoder(); 7 try{ 8 byte[] b = decoder.decodeBuffer(imgStr); 9 String relPath = application.getRealPath("/") ; 10 String path = "/upload/photo.png" ; 11 File f = new File(relPath + path); 12 OutputStream os = new FileOutputStream(f); 13 os.write(b); 14 os.flush(); 15 os.close(); 16 out.println(path); 17 } 18 catch (Exception e) 19 { 20 out.println("error"); 21 } 22 %>
将base64图片内容传给jsp时候。老是会出错。发现是因为“+”传过去就解析成其他符号了。。一直想不明白。。
只能暂时将“+”缓存“#”,到jsp之后在repalce过来,如果有人知道是怎么回事,希望告知下。。
欢迎讨论,转载请注明出处。谢谢!