刚写完一个项目其中就有一个功能修改头像,这个写的我很是头疼。首先做这个有个很大的问题就是图片的压缩,因为用户可能会从手机中上传头像,而手机拍摄的图片往往会很大,所以不可能不对图片进行压缩。不压缩的话一个是上传慢,另一个就是用户产生的流量会很大。所以我们只能进行前端压缩。那么问题来了前端怎么压缩,我在网上找了大量的资料很多人都用jcrop这个控件来做,jcrop会将你上传的图剪裁然后显示出来,但是这个处理过程是在后台进行,说白了就是你还是把原图传到服务器,然后通过剪裁的参数生成剪裁后的图片,这样依然会产生很大的流量。这里我们采用canvas来进行客户端压缩,个人测试很好使想压缩多大就多大,任性!
首先我们在html中写一个显示头像的div。这里需要强调一点 为什么把img和input放到label下,因为我们需要隐藏这个input 但是隐藏后我们很难找到它的位置,于是我们将图片跟它放在一起,起到点击图片就能弹出相册的效果。
定义控件的点击事件以及图片地址变动后的监听事件
$(function(){
var inputFile = document.getElementById('avatarFile')
// 监听文件改变
inputFile.addEventListener('click', function() {this.value = null;}, false);
inputFile.addEventListener('change', readData, false);
})
文件改变响应函数
// 文件改变响应
function readData(evt) {
evt.stopPropagation();
evt.preventDefault();
var file = evt.dataTransfer !== undefined ? evt.dataTransfer.files[0] : evt.target.files[0];
if (!file.type.match(/image.*/)) {return;}
var reader = new FileReader();
reader.onload = (function() {
return function(e) {
var img = new Image();
img.src = e.target.result;
img.onload = (function() {
var canvas = document.createElement('canvas');
canvas.width = 800;
canvas.height = 800;
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height); // canvas清屏
//重置canvans宽高 canvas.width = img.width; canvas.height = img.height;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height); // 将图像绘制到canvas上
canvas.toDataURL("image/jpeg");//必须等压缩完才读取canvas值,否则canvas内容是黑帆布
cropAndUploadImage(canvas.toDataURL("image/jpeg"));
});
}
})(file);
reader.readAsDataURL(file);
}
function cropAndUploadImage(base64){
var b64 = base64.split(",")[1];
var load = layerLoad();
$.ajax({
url: 'User!uploadImg.action',
type: "post",
data:{
photo : b64,
},
dataType: 'json',
success:function(data) {
if(data.success){
setTimeout(function(){
window.location.reload();
},1000);
}else {
layer.close(load);
layerOpen(date.error);
}
},
error : function() {
// view("异常!");
layer.close(load);
layerAlert("图片上传超时!");
}
})
}
/**
* 上传图片
* @return
*/
public String uploadImg() {
JSONObject info = new JSONObject();
try {
getRequest().setCharacterEncoding("utf-8");
getResponse().setCharacterEncoding("utf-8");
getResponse().setContentType("text/html");
int userid = (int)getSession().get("userid");
String path = "/image/user/";
// 对base64数据进行解码 生成 字节数组,不能直接用Base64.decode();进行解密
byte[] photoimg = new BASE64Decoder().decodeBuffer(photo);
for (int i = 0; i < photoimg.length; ++i) {
if (photoimg[i] < 0) {
// 调整异常数据
photoimg[i] += 256;
}
}
//byte[] photoimg = Base64.decode(photo);//此处不能用Base64.decode()方法解密,我调试时用此方法每次解密出的数据都比原数据大 所以用上面的函数进行解密,在网上直接拷贝的,花了好几个小时才找到这个错误(菜鸟不容易啊)
File file = new File(getRequest().getServletContext().getRealPath(path), userid + ".JPEG");
if (!file.exists()) {
file.createNewFile();
}
FileOutputStream out = new FileOutputStream(file);
out.write(photoimg);
out.flush();
out.close();
/**
* 更改数据库图片地址
*/
// 图片地址存入数据库 这里就不详细介绍了
info.accumulate("success", true);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
info.accumulate("success", false).accumulate("error", "图片太大,设置失败");
}
super.responsePrint(info.toString());
return null;
}