springMVC 头像裁剪上传并等比压
第一次写头像裁剪上传,原本想着直接本地预览裁剪再上传,可是时间有限,jquery.jcrop貌似并没有对 假设是ie下图片预览效果是滤镜做的 做出对应处理,也没有时间去改;仅仅好将就一下先把图片上传上去再预览
1.先看一下我引入的js
<script src="${adminBasePath}resources/js/jquery.1.8.3.js"></script>
<script src="${adminBasePath}resources/js/layer.js"></script>
<script src="${adminBasePath}resources/js/jquery.jcrop.js"></script>
<script src="${adminBasePath}resources/js/ajaxfileupload.js"></script>
<script src="${adminBasePath}resources/js/perview-image.js"></script>
2.当中perview-image.js是从一位友友哪里粘贴过去的,名字忘了不好意思;(由于我用的是require。所以这里没拆出来)
define(function() {
return {
timers : [],
closeImg : {
before : "",
after : ""
},
loading : "",
fileImg : "",
// 获取预览元素
getElementObject : function(elem) {
if (elem.nodeType && elem.nodeType === 1) {
return elem;
} else {
return document.getElementById(elem);
}
},
// 開始图片预览
beginPerview : function(/* 文件上传控件实例 */file, /* 须要显示的元素id或元素实例 */
perviewElemId,/* 上传页面所在的document对象 */dcmt,/* 文件后缀名 */fileSuf) {
var imgSufs = ",jpg,jpeg,bmp,png,gif,";
var isImage = imgSufs.indexOf("," + fileSuf.toLowerCase() + ",") > -1;// 检查是否为图片 if (isImage) {
this.imageOperation(file, perviewElemId, dcmt);
} else {
this.fileOperation(perviewElemId, fileSuf);
}
},
// 一般文件显示操作
fileOperation : function(/* 须要显示的元素id或元素实例 */perviewElemId,/* 文件后缀名 */
fileSuf) {
var that=this;
var preview_div = this.getElementObject(perviewElemId); var MAXWIDTH = preview_div.clientWidth;
var MAXHEIGHT = preview_div.clientHeight;
var img = document.createElement("img");
preview_div.appendChild(img);
img.style.visibility = "hidden";
img.src = this.fileImg;
img.onload = function() {
var rect = that.clacImgZoomParam(MAXWIDTH, MAXHEIGHT,
img.offsetWidth, img.offsetHeight);
img.style.width = rect.width + 'px';
img.style.height = rect.height + 'px';
img.style.marginLeft = rect.left + 'px';
img.style.marginTop = rect.top + 'px';
img.style.visibility = "visible";
}
var txtTop = 0 - (MAXHEIGHT * 2 / 3);
$(
'<div style="text-align:center; position:relative; z-index:100; color:#404040;font: 13px/27px Arial,sans-serif;"></div>')
.text(fileSuf + "文件").css("top", txtTop + "px").appendTo(
preview_div); },
// 图片预览操作
imageOperation : function(/* 文件上传控件实例 */file, /* 须要显示的元素id或元素实例 */
perviewElemId,/* 上传页面所在的document对象 */dcmt) {
var that=this;
for (var t = 0; t < this.timers.length; t++) {
window.clearInterval(this.timers[t]);
}
this.timers.length = 0; var preview_div = this.getElementObject(perviewElemId); var MAXWIDTH = preview_div.clientWidth;
var MAXHEIGHT = preview_div.clientHeight; if (file.files && file.files[0]) { // 此处为Firefox。Chrome以及IE10的操作
preview_div.innerHTML = "";
var img = document.createElement("img");
preview_div.appendChild(img);
img.style.visibility = "hidden";
img.onload = function() {
var rect = that.clacImgZoomParam(MAXWIDTH,
MAXHEIGHT, img.offsetWidth, img.offsetHeight);
img.style.width = rect.width + 'px';
img.style.height = rect.height + 'px';
img.style.marginLeft = rect.left + 'px';
img.style.marginTop = rect.top + 'px';
img.style.visibility = "visible";
}
if(file.isURL){
img.src=file.files[0];
return false;
}
var reader = new FileReader();
reader.onload = function(evt) {
img.src = evt.target.result;
}
reader.readAsDataURL(file.files[0]);
} else {// 此处为IE6,7。8,9的操作
file.select();
file.blur();
var src = dcmt.selection.createRange().text;
var div_sFilter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='scale',src='"
+ src + "')";
var img_sFilter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='image',src='"
+ src + "')"; preview_div.innerHTML = "";
var img = document.createElement("div");
preview_div.appendChild(img);
img.style.filter = img_sFilter;
img.style.visibility = "hidden";
img.style.width = "100%";
img.style.height = "100%"; function setImageDisplay() {
var rect = that.clacImgZoomParam(MAXWIDTH,
MAXHEIGHT, img.offsetWidth, img.offsetHeight);
preview_div.innerHTML = "";
var div = document.createElement("div");
div.style.width = rect.width + 'px';
div.style.height = rect.height + 'px';
div.style.marginLeft = rect.left + 'px';
div.style.marginTop = rect.top + 'px';
div.style.filter = div_sFilter; preview_div.appendChild(div);
} // 图片载入计数
var tally = 0; var timer = window.setInterval(function() {
if (img.offsetHeight != MAXHEIGHT) {
window.clearInterval(timer);
setImageDisplay();
} else {
tally++;
}
// 假设超过两秒钟图片还不能载入,就停止当前的轮询
if (tally > 20) {
window.clearInterval(timer);
setImageDisplay();
}
}, 100); this.timers.push(timer);
}
},
// 按比例缩放图片
clacImgZoomParam : function(maxWidth, maxHeight, width, height) {
var param = {
width : width,
height : height
};
if (width > maxWidth || height > maxHeight) {
var rateWidth = width / maxWidth;
var rateHeight = height / maxHeight; if (rateWidth > rateHeight) {
param.width = maxWidth;
param.height = Math.round(height / rateWidth);
} else {
param.width = Math.round(width / rateHeight);
param.height = maxHeight;
}
} param.left = Math.round((maxWidth - param.width) / 2);
param.top = Math.round((maxHeight - param.height) / 2);
return param;
},
// 创建图片预览元素
createPreviewElement : function(/* 关闭图片名称 */name,/* 上传时的文件名称 */file, /* 预览时的样式 */
style) {
var img = document.createElement("div");
img.title = file;
img.style.overflow = "hidden";
for ( var s in style) {
img.style[s] = style[s];
} var text = document.createElement("div");
text.style.width = style.width;
text.style.overflow = "hidden";
text.style.textOverflow = "ellipsis";
text.style.whiteSpace = "nowrap";
text.innerHTML = file; var top = 0 - window.parseInt(style.width) - 15;
var right = 0 - window.parseInt(style.width) + 14;
var close = document.createElement("img");
close.setAttribute("name", name);
close.src = this.closeImg.before;
close.style.position = "relative";
close.style.top = top + "px";
close.style.right = right + "px";
close.style.cursor = "pointer"; var loadtop = (0 - window.parseInt(style.height)) / 2 - 26;
var loadright = (0 - window.parseInt(style.width)) / 2 + 22;
var imgloading = document.createElement("img");
imgloading.src = this.loading;
imgloading.style.position = "relative";
imgloading.style.top = loadtop + "px";
imgloading.style.right = loadright + "px";
imgloading.style.display = "none"; var main = document.createElement("div");
main.appendChild(img);
main.appendChild(text);
main.appendChild(close);
main.appendChild(imgloading);
return main;
}, // 获取预览区域
getPerviewRegion : function(elem) {
var perview = $(this.getElementObject(elem));
if (!perview.find("ul").length) {
var ul = document.createElement("ul");
ul.style.listStyleType = "none";
ul.style.margin = "0px";
ul.style.padding = "0px"; var div = document.createElement("div");
div.style.clear = "both";
perview.append(ul).append(div);
return ul;
} else {
return perview.children("ul").get(0);
}
},
// 获取上传文件大小
getFileSize : function(/* 上传控件dom对象 */file, /* 上传控件所在的document对象 */
dcmt) {
var fileSize;
if (file.files && file.files[0]) {
fileSize = file.files[0].size;
} else {
file.select();
var src = dcmt.selection.createRange().text;
try {
var fso = new ActiveXObject("Scripting.FileSystemObject");
var fileObj = fso.getFile(src);
fileSize = fileObj.size;
} catch (e) {
return "error";
}
}
fileSize = ((fileSize / 1024) + "").split(".")[0];
return fileSize;
}
}
});
3.然后先看我前端的代码
<script type="text/html" id="upload_photo_tml">
<div class="upload-photo">
<div class="photo-lg-pre pre-img">
<div class="img-border" id="img-border"> </div>
</div>
<div class="photo-up-op">
<div class="photo-sm-pre" id="preview-pane">
<img src="${imgPath}header-img2.png" class="headimg-top" />
<div class="preview-container"> </div>
</div>
<div class="photo-up-btn" align="center">
<input type="file" name="userPhoto" id="userPhoto" />
<span class="file-button" id="upload-file-btn" data-id="userPhoto">选择图片</span>
</div>
</div>
</div>
</script>
$(document).on("click","#headImage",function(){
var index=layer.confirm($("#upload_photo_tml").html(), {
title:"上传头像",
btn: ['确定','取消'] //button
}, function(){
if(opts.selectData.w==undefined)
return false;
//确定上传 type 为1
opts.uploadType=1;
var data={
type:opts.uploadType,
x:opts.selectData.x,
y:opts.selectData.y,
width:opts.selectData.w,
height:opts.selectData.h
};
if(opts.uploadData!=null){
data.paramString=encodeURI(JSON.stringify(opts.uploadData));
}
ajaxfileupload.ajaxFileUpload({
url: opts.uploadPhotoURL,
type: 'post',
secureuri: false,
// 一般设置为false
data: data,
fileElementId: "userPhoto",
// 上传文件的id、name属性名
dataType: 'json',
// 返回值类型,一般设置为json、application/json
success: function(data, status) {
if(data.responseCode&&data.responseCode==200){
$(opts.userHeadPhoto).attr("src",adminBasePath+data.fileURL+data.fileName);
layer.alert("上传成功!",{icon:1});
}else{
layer.alert("上传失败!",{icon:2});
}
},
error: function(data, status, e) {
console.log(e);
}
});
});
});
$(document).on("change",'#userPhoto',function(e) {
//假设仅仅是预览 type为0
opts.uploadType=0;
$(".preview-container").html("");
var data={
type:opts.uploadType,
x:0,
y:0,
width:0,
height:0
};
if(opts.uploadData!=null){
data.paramString=encodeURI(JSON.stringify(opts.uploadData));
}
var loadingIndex=layer.load(0, {shade: false});
var userPhotoHTML=$("#userPhoto").prop("outerHTML");
ajaxfileupload.ajaxFileUpload({
url: opts.uploadPhotoURL,
type: 'post',
secureuri: false,
// 一般设置为false
data: data,
fileElementId: "userPhoto",
// 上传文件的id、name属性名
dataType: 'json',
// 返回值类型,一般设置为json、application/json
success: function(data, status) {
opts.uploadType=1;
opts.uploadData=data;
perviewImage.imageOperation({files:[adminBasePath+data.fileURL+data.fileName+"?date="+ (new Date()).getTime()],isURL:true},"img-border",document);
layer.close(loadingIndex);
if(opts.jcrop_api!=null)
opts.jcrop_api.destroy();
opts.xsize = $(opts.pcnt).width();
opts.ysize = $(opts.pcnt).height();
$('#img-border>img').Jcrop({
bgColor: "#ffffff",
onChange: that._updatePreview,
onSelect: that._updatePreview,
aspectRatio: opts.xsize / opts.ysize
},function(){
// var _w=$(".jcrop-holder>img").width(),
// _h=$(".jcrop-holder>img").height(),
// _wh=0;
// if(_w>=_h)
// _wh=_w;
// else
// _wh=_h;
var bounds = this.getBounds();
opts.boundx = bounds[0];
opts.boundy = bounds[1];
opts.jcrop_api = this;
//opts.jcrop_api.setSelect([0,0,_wh,_wh]);
$(".preview-container").html($("#img-border").html());
$(".photo-up-btn").prepend(userPhotoHTML);
});
},
error: function(data, status, e) {
console.log(e);
}
});
});
//绘制选框
that._updatePreview = function(c) {
var opts=that.opts;
opts.selectData=c;
if (parseInt(c.w) > 0) {
var rx = opts.xsize / c.w;
var ry = opts.ysize / c.h;
$(opts.pimg).css({
width : Math.round(rx * opts.boundx) + 'px',
height : Math.round(ry * opts.boundy) + 'px',
marginLeft : '-' + Math.round(rx * c.x) + 'px',
marginTop : '-' + Math.round(ry * c.y) + 'px'
});
}
};
4.然后是Controller层以及图片上传方法的代码
/**
* 用户上传头像
*
* @param type
* 0表示暂时预览,1表示上传确认头像
* @return
*/
@ResponseBody
@RequestMapping(value = "upload/userphoto", method = RequestMethod.POST)
public void uploadUserphoto(Integer type, double x, double y, double width,
double height) {
JSONObject obj = new JSONObject();
try {
String paramString = "";
JSONObject paj = null;
if (null != getRequest().getParameter("paramString")) {
paramString = URLDecoder.decode(
getRequest().getParameter("paramString"), "UTF-8");
paj = (JSONObject) JSON.parse(paramString);
}
if (type == 1) {
String url = getRequest().getSession().getServletContext()
.getRealPath(paj.getString("fileURL"));
String isOK = UploadImgUtil.cutImage(
url + "\\" + paj.getString("fileName"),
paj.getString("fileURL"), paj.getString("fileName"), x,
y, width, height);
if (isOK.equals("y")) {
String params = HttpRequestUtil.sendPost(
"updateUserAvatar", "loginToken="
+ getCookieUtil().getCookieValue("L_TOKEN")
+ "&userAvatar=" + paj.getString("fileURL")
+ paj.getString("fileName"));
obj.put("responseCode", ((JSONObject) JSONObject
.parse(params)).get("responseCode"));
obj.put("fileURL", paj.getString("fileURL"));
obj.put("fileName", paj.getString("fileName"));
} else {
obj.put("responseCode", "402");
obj.put("responseText", "上传失败");
}
} else {
obj = UploadImgUtil.uploadPhotoImgUrls(getRequest(), super
.getUser().getId().toString(), paramString == "" ? ""
: paj.getString("fileURL"), paramString == "" ? ""
: paj.getString("fileName"));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
obj.put("responseCode", "402");
obj.put("responseText", "上传失败");
}
writeHtml(obj.toJSONString());
}
<pre name="code" class="java">/**
* 图片裁剪通用接口
*
* @param src
* 原图地址
* @param path
* 存放路径
* @param name
* 存放名称
* @param x
* @param y
* @param w
* @param h
* @throws IOException
*/
public static String cutImage(String src, String path, String name,
double x, double y, double w, double h) throws IOException {
Image img;
ImageFilter cropFilter;
String ext = getExtension(name);
if (ext == null)
ext = "jpg";
BufferedImage bi = ImageIO.read(new File(src)); double rate1 = ((double) bi.getWidth()) / (double) UPLOADPHOTOWIDTH
+ 0.1;
double rate2 = ((double) bi.getHeight()) / (double) UPLOADPHOTOWIDTH
+ 0.1;
// 依据缩放比率大的进行缩放控制
double rate = 0d;
if (bi.getWidth() > UPLOADPHOTOWIDTH
|| bi.getHeight() > UPLOADPHOTOWIDTH)
rate = rate1 > rate2 ? rate1 : rate2;
else
rate = rate1 < rate2 ? rate1 : rate2; BufferedImage tag;
Image image = bi.getScaledInstance(bi.getWidth(), bi.getHeight(),
Image.SCALE_DEFAULT);
// 四个參数分别为图像起点坐标和宽高
// 即: CropImageFilter(int x,int y,int width,int height)
cropFilter = new CropImageFilter(
rate1 > 1 ? (int) (x * rate) : (int) x,
rate2 > 1 ? (int) (y * rate) : (int) y,
rate1 > 1 ? (int) (w * rate) : (int) w,
rate2 > 1 ? (int) (h * rate) : (int) h);
img = Toolkit.getDefaultToolkit().createImage(
new FilteredImageSource(image.getSource(), cropFilter));
int type = BufferedImage.TYPE_INT_RGB;
if ("gif".equalsIgnoreCase(ext) || "png".equalsIgnoreCase(ext)) {
type = BufferedImage.TYPE_INT_ARGB;
} int newWidth;
int newHeight;
// 推断是否是等比缩放
if ((w * rate) > 640 || (h * rate) > 640) {
// 为等比缩放计算输出的图片宽度及高度
double rate3 = (w * rate) / (double) OUTPUTWIDTH + 0.1;
double rate4 = (h * rate) / (double) OUTPUTWIDTH + 0.1;
// 依据缩放比率大的进行缩放控制
double nrate = rate3 > rate4 ? rate3 : rate4;
newWidth = (int) ((w * rate) / nrate);
newHeight = (int) ((h * rate) / nrate);
} else {
newWidth = rate1 > 1 ? (int) (w * rate) : (int) w; // 输出的图片宽度
newHeight = rate2 > 1 ? (int) (h * rate) : (int) h; // 输出的图片高度
} tag = new BufferedImage(newWidth, newHeight, type); Graphics2D g = (Graphics2D) tag.getGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.dispose(); g = tag.createGraphics();
tag = g.getDeviceConfiguration().createCompatibleImage(newWidth,
newHeight, Transparency.TRANSLUCENT);
g.dispose(); g = tag.createGraphics(); img = img.getScaledInstance(newWidth, newHeight,
img.SCALE_AREA_AVERAGING); g.drawImage(img, 0, 0, null); // 绘制剪切后的图
g.dispose(); ImageIO.write(tag, "png", new File(src));
return "y";
} public static String getExtension(String srcImageFile) {
String ext = null;
if (srcImageFile != null && srcImageFile.lastIndexOf(".") > -1) {
ext = srcImageFile.substring(srcImageFile.lastIndexOf(".") + 1);
}
return ext;
}
springMVC 头像裁剪上传并等比压的更多相关文章
- 第三百九十节,Django+Xadmin打造上线标准的在线教育平台—Django+cropper插件头像裁剪上传
第三百九十节,Django+Xadmin打造上线标准的在线教育平台—Django+cropper插件头像裁剪上传 实现原理 前台用cropper插件,将用户上传头像时裁剪图片的坐标和图片,传到逻辑处理 ...
- jfinal头像裁剪上传服务器
前端页面完整代码,复制可用,记得导入库文件 <!DOCTYPE html> <html lang="en"> <head> <title& ...
- mui+vue+photoclip做APP头像裁剪上传
做APP由于项目需要,需要做用户头像上传的功能,头像上传包括拍照和相册选择图片进行上传,这里使用的技术是mui封装的plus,在进行图片裁剪的时候,使用的是photoclip来进行裁剪,由于个人在使用 ...
- springmvc+ajax文件上传
环境:JDK6以上,这里我是用JDK8,mysql57,maven项目 框架环境:spring+springmvc+mybaits或spring+springmvc+mybatis plus 前端代码 ...
- 5.21学习总结——android开发实现用户头像的上传
最近在做个人头像的上传,具体是能调用摄像头和从相册进行选择.本篇文章参考的我的同学的博客,大家有兴趣可以去原作者那里去看看: Hi(.・∀・)ノ (cnblogs.com) 1.使用glide进行图片 ...
- springmvc图片文件上传接口
springmvc图片文件上传 用MultipartFile文件方式传输 Controller package com.controller; import java.awt.image.Buffer ...
- SpringMVC学习--文件上传
简介 文件上传是web开发中常见的需求之一,springMVC将文件上传进行了集成,可以方便快捷的进行开发. springmvc中对多部件类型解析 在 页面form中提交enctype="m ...
- Spring +SpringMVC 实现文件上传功能。。。
要实现Spring +SpringMVC 实现文件上传功能. 第一步:下载 第二步: 新建一个web项目导入Spring 和SpringMVC的jar包(在MyEclipse里有自动生成spring ...
- springMVC+jsp+ajax上传文件
工作中遇到的小问题,做个笔记 实现springMVC + jsp + ajax 上传文件 HTML <body> <form id="myform" method ...
随机推荐
- es6解构赋值总结
数组的解构赋值 1.简单的赋值方式 2.多维数组解构赋值 3.默认值,只有当右边对应位置为undefined时候才会选择默认(null不属于undefined) 4.左右不对等,会相应的对号入座,没有 ...
- YII2源码阅读:autoload_real.php 22~23行
spl_autoload_register(array('ComposerAutoloaderInit32b8eb537f8e12e57c5e7bade69d01f0', 'loadClassLoad ...
- Oracle 使用序列、触发器实现自增
之前项目开发多用mysql,对于id自增长设置,只需要简单修改列属性便好.最近改用ORACLE,头大一圈.ORACLE的相关操作,多用脚本.想短平快,难.最终用sql developer通过UI进行修 ...
- POJ 1200 Crazy Search【Hash入门】
RK法:https://www.cnblogs.com/16crow/p/6879988.html #include<cstdio> #include<string> #inc ...
- Python3 文件读写r,w,a
# Author;Tsukasa ''' f = open('yesterday','w') #文件句柄...注意open分为‘r’读模式,‘w’写模式(d会先创建文件或者覆盖文件),‘a’为追加模式 ...
- 【小摘抄】关于C++11下 string各类用法(持续更新)
http://blog.csdn.net/autocyz/article/details/42391155 提供了最简单的详解 下列对本人近期开发中的一些心得体会进行摘抄 1.string按照字符进行 ...
- Sqli-labs less 4
Less-4 我们使用?id=1" 注入代码后,我们得到像这样的一个错误: You have an error in your SQL syntax; check the manual th ...
- BZOJ 1430 小猴打架(prufer编码)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1430 [题目大意] 一开始森林里面有N只互不相识的小猴子,它们经常打架, 但打架的双方 ...
- [移动应用安全]移动应用安全培训PPT
这是年初给公司做的移动应用安全培训,主要是针对开发的兄弟们,让大家对目前的移动领域的安全形势有个了解,以及不正确的开发所带来的危害,另外还配了个详细的word版的移动应用开发指南,后面一起附上:).
- 基于tiny4412的Linux内核移植 -- PWM子系统学习(八)
作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...