最近在做项目时候需要一个头像长传功能,但是现在照片动不动就几兆的,都是流量的浪费。

我只是简单想要上传一个头像而已。。。

经过几天发愤图强。。总算是略有所获。。

基本思路:

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过来,如果有人知道是怎么回事,希望告知下。。

欢迎讨论,转载请注明出处。谢谢!

基于canvas和jsp的头像剪辑上传的更多相关文章

  1. 头像截图上传三种方式之一(一个简单易用的flash插件)(asp.net版本)

    flash中有版权声明,不适合商业开发.这是官网地址:http://www.hdfu.net/ 本文参考了http://blog.csdn.net/yafei450225664/article/det ...

  2. JSP实现大文件上传和下载

    javaweb上传文件 上传文件的jsp中的部分 上传文件同样可以使用form表单向后端发请求,也可以使用 ajax向后端发请求 1.通过form表单向后端发送请求 <form id=" ...

  3. RPC基于http协议通过netty支持文件上传下载

    本人在中间件研发组(主要开发RPC),近期遇到一个需求:RPC基于http协议通过netty支持文件上传下载 经过一系列的资料查找学习,终于实现了该功能 通过netty实现文件上传下载,主要在编解码时 ...

  4. 第三百九十节,Django+Xadmin打造上线标准的在线教育平台—Django+cropper插件头像裁剪上传

    第三百九十节,Django+Xadmin打造上线标准的在线教育平台—Django+cropper插件头像裁剪上传 实现原理 前台用cropper插件,将用户上传头像时裁剪图片的坐标和图片,传到逻辑处理 ...

  5. springMVC 头像裁剪上传并等比压

    第一次写头像裁剪上传,原本想着直接本地预览裁剪再上传,可是时间有限,jquery.jcrop貌似并没有对 假设是ie下图片预览效果是滤镜做的  做出对应处理,也没有时间去改;仅仅好将就一下先把图片上传 ...

  6. jsp+servlet实现文件上传下载

    相关素材下载 01.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" ...

  7. 5.21学习总结——android开发实现用户头像的上传

    最近在做个人头像的上传,具体是能调用摄像头和从相册进行选择.本篇文章参考的我的同学的博客,大家有兴趣可以去原作者那里去看看: Hi(.・∀・)ノ (cnblogs.com) 1.使用glide进行图片 ...

  8. CANVAS运用-对图片的压缩上传(仅针对移动浏览器)

    最近在移动端设计头像上传功能时,原本是以<input type="file">直接通过formData上传,然而实际使用情况是:对于过大的图片(高像素手机所拍摄的照片等 ...

  9. html5,js插件实现手机端实现头像剪切上传

    思路:先打开相册,选取图片,在剪切图片,转化为base64格式,然后上传到七牛存储,返回url,再传给后端,整个流程就是这样.用的是angular框架,图像插件用到imagecropper.js,废话 ...

随机推荐

  1. javascript之日期对象

    学习要点: 日期对象 将日期对象转换为字符串 将日期对象中的日期和时间转换为字符串 日期对象中的日期 日期对象中的时间 设置日期对象中的日期 设置日期对象中的时间 与毫秒相关的方法 一.日期对象 在j ...

  2. displayport

    去年买了一张ATI的显卡,但是很坑爹的是显卡后面没有VGA接口,除了一个HDMI,另外两个接口不认识,后来认识了DVI,用DVI连接显示器,剩下一个接口是什么一直没管,前两天电脑清灰,感兴趣了,去查了 ...

  3. Git和Github的配合使用

    Git教程 http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 Git 本地仓库详解  ...

  4. UVa 311 - Packets

    题目大意:有1X1,2X2 ... 5X5,6X6六种类型的物品,把他们装进6X6的盒子里,求使用的最少盒子数. 贪心吧,其实一看就知道思路了,算是常识吧,装物品时通常都是先装大的,再在其余空间放小的 ...

  5. UVa 270 & POJ 1118 - Lining Up

    题目大意:给一些点,找出一条直线使尽可能多的点在这条直线上,求这条直线上点的个数. 以每一个点为原点进行枚举,求其它点的斜率,斜率相同则说明在一条直线上.对斜率排序,找出斜率连续相等的最大长度. #i ...

  6. Python装饰器学习(九步入门)

    这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 ? 1 2 3 4 5 6 7 8 # -*- coding:gbk -*- '''示 ...

  7. OpenSceneGraph几个重要功能节点练习

    OpenSceneGraph几个重要功能节点练习 一. 空间变换节点 空间变换中最重要的是坐标系和矩阵运算了.OSG坐标系中使用右手系,Z轴垂直向上,X轴水平向右,Y轴垂直屏幕向里,与OpenGL和D ...

  8. DEV组件LookupEdit,ComboBoxEdit绑定数据源

    LookupEdit可以绑定数据表(DataTable)或对象数据组(Object List)作为数据源,下拉窗体可自定显示栏位. 绑定数据源需要设置三个参数:DisplayMember ,Value ...

  9. PAT1013 数素数

    思路: 打印素数表 然后找出对应区间[m,n]中的素数 #include <iostream> #include <vector> #include <cmath> ...

  10. MySQL5.6多实例部署

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://suifu.blog.51cto.com/9167728/1850560 无论是迫 ...