花了几天时间学习了下javaWeb中cropper头像上传功能,下面仅在此记录一下.
看到有篇博客是在前台用canvas的toDataURL处理,但貌似无法处理gif图像(如有大侠知道如何处理,还望告知),故放弃这一做法而选择在后端处理,
前台提交scaleX,scaleY,rotate,x,y,width,height及原始图片,后台缩放、旋转、裁剪.
一、下面先提供一个处理类:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import org.apache.commons.lang3.StringUtils;
import com.lzw.gif.AnimatedGifEncoder;
import com.lzw.gif.GifDecoder;
/**
* @author nc-wl001 配合cropper头像上传插件使用的bean、(注意cropper插件缩放后图片大小是不变的及图片中心是不变的)
*/
public class Cropper {
//水平方向缩放比例
private double scaleX;
//垂直方向缩放比例
private double scaleY;
// 旋转角度15、45等
private int rotate;
// 注意以下数据均是相对于旋转后的图片
// 裁剪框左上角x
private int x;
// 裁剪框左上角y
private int y;
// 裁剪框宽度
private int width;
// 裁剪框高度
private int height;
// 为防止目标图片过大而添加的一个缩放比例参数
protected double scale = 1.0;
public Cropper(double scaleX,double scaleY,int rotate, int x, int y, int width, int height) {
super();
this.scaleX=scaleX;
this.scaleY=scaleY;
this.rotate = rotate;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public int getRotate() {
return rotate;
}
public void setRotate(int rotate) {
this.rotate = rotate;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public double getScaleX() {
return scaleX;
}
public void setScaleX(double scaleX) {
this.scaleX = scaleX;
}
public double getScaleY() {
return scaleY;
}
public void setScaleY(double scaleY) {
this.scaleY = scaleY;
}
/**
* 设置缩放比例
*
* @param scale
*/
protected void setScale(double scale) {
this.x = (int) Math.ceil(this.x * scale / this.scale);
this.y = (int) Math.ceil(this.y * scale / this.scale);
this.width = (int) Math.ceil(this.width * scale / this.scale);
this.height = (int) Math.ceil(this.height * scale / this.scale);
this.scale = scale;
}
/**
* 设置目标图片宽度
*
* @param width
*/
public void setFactWidth(int width) {
double scale = width * this.scale / this.width;
this.setScale(scale);
}
/**
* 设置目标图片高度
*
* @param height
*/
public void setFactHeight(int height) {
double scale = height * this.scale / this.height;
this.setScale(scale);
}
/**
* 获取源图片旋转后的目标容器大小
*
* @param source
* 源图片大小
* @return
*/
protected final Dimension getTargetDimension(Dimension source) {
source.setSize(source.getWidth() * this.scale, source.getHeight()
* this.scale);
// 获取旋转后图片大小
double theta = Math.toRadians(this.rotate);
double target_width, target_height;
if ((int) Math.floor(this.rotate / 90.0) % 2 == 0) {// 也即Math.sin(2*theta)>0(Math.sin(2*theta)=0时两个分支结果一样)
target_width = Math.abs(source.width * Math.cos(theta)
+ source.height * Math.sin(theta));
target_height = Math.abs(source.height * Math.cos(theta)
+ source.width * Math.sin(theta));
} else {
target_width = Math.abs(source.width * Math.cos(theta)
- source.height * Math.sin(theta));
target_height = Math.abs(source.height * Math.cos(theta)
- source.width * Math.sin(theta));
}
Dimension target = new Dimension();
target.setSize(target_width, target_height);
return target;
}
/**
* 获取旋转并裁剪后的图片
*
* @param src
* 源图片
* @return 旋转并裁剪后的图片
*/
protected final BufferedImage rotate_CropImage(BufferedImage src) {
// 原图大小
Dimension source = new Dimension(src.getWidth(), src.getHeight());
// 旋转后大小
Dimension target = this.getTargetDimension(source);
// 旋转并裁剪后的目标图片
BufferedImage rotate_crop_Image = new BufferedImage(this.width,
this.height, BufferedImage.TYPE_INT_RGB);
Graphics2D rotate_crop_g2d = rotate_crop_Image.createGraphics();
// 设置填充色为白色
rotate_crop_g2d.setColor(Color.WHITE);
rotate_crop_g2d.fillRect(0, 0, this.width, this.height);
// transform;translate(x,y)是将坐标系往右平移x,往下平移y,(x,y的正负对应正反方向)
rotate_crop_g2d.translate((target.width - source.width) / 2 - this.x,
(target.height - source.height) / 2 - this.y);// 平移坐标系(以便后面将原图画上去)
// rotate 旋转坐标系
rotate_crop_g2d.rotate(Math.toRadians(this.rotate), source.width / 2,
source.height / 2);// 旋转坐标系、注意旋转中心
rotate_crop_g2d.translate((1-this.scaleX)*source.width/2, (1-this.scaleY)*source.height/2);
// 将图画上去
rotate_crop_g2d.drawImage(src,AffineTransform.getScaleInstance(this.scale*this.scaleX, this.scale*this.scaleY), null);// 画图
rotate_crop_g2d.dispose();
return rotate_crop_Image;
}
/**
* 获取旋转并裁剪后的图片二进制流
*
* @param inputStream
* 图片文件输入流
* @param imageType
* 图片文件类型(jpeg,png,jpg,gif等)
* @return 旋转并裁剪后的图片二进制流
*/
public byte[] rotate_CropImage(InputStream inputStream, String imageType) {
byte[] result = new byte[] {};
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
if (StringUtils.equalsIgnoreCase(imageType, "gif")) {
/*----------------AnimatedGifEncoder.java处理----------------------*/
GifDecoder decoder = new GifDecoder();
decoder.read(inputStream);
AnimatedGifEncoder encoder = new AnimatedGifEncoder();
encoder.start(outputStream);// 若要生成gif图片则使用encoder.start("xxx.gif");
encoder.setRepeat(decoder.getLoopCount());
for (int i = 0, n = decoder.getFrameCount(); i < n; i++) {
encoder.setDelay(decoder.getDelay(i));
encoder.addFrame(this.rotate_CropImage(decoder.getFrame(i)));
}
encoder.finish();
} else {// 其他格式图片文件处理
ImageIO.write(this.rotate_CropImage(ImageIO.read(inputStream)),
imageType, outputStream);
}
result = outputStream.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
}
说明:此类是基于Cropper插件的几个裁剪数据而建的,可处理动态图,动态图处理部分是在网上找的几个处理gif的类.
这里打成了jar包方便使用:http://download.csdn.net/download/xinshijimanon/9796051;
此类的重点是后三个方法,由于本人表达能力先天欠缺,就不详细熬叙此方法了(主要是获取旋转后的图片大小,以及在scaleX,scaleY不为1时如何将坐标系平移、旋转到正确位置)。
二、前台部分代码:
我这里是以弹窗的形式弹出修改头像框的,用的是layer插件,请酌情替换.
1、html/jsp
<!-- 修改头像2 -->
<div id="editPhotoDialog" class="dialog">
<label class="btn btn-primary btn-upload" for="inputImage" style="margin: 15px;">
<input type="file" class="sr-only" id="inputImage" accept=".jpg,.jpeg,.png,.gif,.bmp">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="上传图片文件(.jpg、.jpeg、.png、.gif、.bmp)">
<span class="icon icon-upload"> 选择图片</span>
</span>
</label>
<div>
<div class="col-md-8">
<!-- <h3>Demo:</h3> -->
<div class="img-container" style="width:390px;height:390px;">
<img id="image" src="">
</div>
</div>
<div class="col-md-3">
<!-- <h3>Preview:</h3> -->
<div class="docs-preview clearfix">
<div class="img-preview preview-lg"></div>
<div class="img-preview preview-md"></div>
<div class="img-preview preview-sm"></div>
<div class="img-preview preview-xs"></div>
</div>
</div>
</div>
<div>
<div class="col-md-9 docs-buttons">
<div class="btn-group">
<button class="btn btn-primary" data-method="zoom" data-option="0.1" type="button" title="Zoom In">
<span class="docs-tooltip" data-toggle="tooltip" title="放大">
<span class="icon icon-zoom-in"></span>
</span>
</button>
<button class="btn btn-primary" data-method="zoom" data-option="-0.1" type="button" title="Zoom Out">
<span class="docs-tooltip" data-toggle="tooltip" title="缩小">
<span class="icon icon-zoom-out"></span>
</span>
</button>
<button class="btn btn-primary" data-method="rotate" data-option="-45" type="button" title="Rotate Left">
<span class="docs-tooltip" data-toggle="tooltip" title="左旋转45度">
<span class="icon icon-rotate-left"></span>
</span>
</button>
<button class="btn btn-primary" data-method="rotate" data-option="45" type="button" title="Rotate Right">
<span class="docs-tooltip" data-toggle="tooltip" title="右旋转45度">
<span class="icon icon-rotate-right"></span>
</span>
</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-primary" data-method="move" data-option="-2" data-second-option="0" title="Move Left">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="左移">
<span class="icon icon-arrow-left"></span>
</span>
</button>
<button type="button" class="btn btn-primary" data-method="move" data-option="2" data-second-option="0" title="Move Right">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="右移">
<span class="icon icon-arrow-right"></span>
</span>
</button>
<button type="button" class="btn btn-primary" data-method="move" data-option="0" data-second-option="-2" title="Move Up">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="上移">
<span class="icon icon-arrow-up"></span>
</span>
</button>
<button type="button" class="btn btn-primary" data-method="move" data-option="0" data-second-option="2" title="Move Down">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="下移">
<span class="icon icon-arrow-down"></span>
</span>
</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-primary" data-method="addScaleX" data-option="0.08" data-second-option="2" data-three-option="3" title="Flip Horizontal">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="水平放大">
<span class="icon icon-chevron-left"></span>
</span>
</button>
<button type="button" class="btn btn-primary" data-method="addScaleX" data-option="-0.08" data-second-option="2" data-three-option="3" title="Flip Horizontal">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="水平缩小">
<span class="icon icon-chevron-right"></span>
</span>
</button>
<button type="button" class="btn btn-primary" data-method="addScaleY" data-option="0.08" data-second-option="2" data-three-option="3" title="Flip Vertical">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="竖直放大">
<span class="icon icon-chevron-up"></span>
</span>
</button>
<button type="button" class="btn btn-primary" data-method="addScaleY" data-option="-0.08" data-second-option="2" data-three-option="3" title="Flip Vertical">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="竖直缩小">
<span class="icon icon-chevron-down"></span>
</span>
</button>
</div>
</div>
</div>
</div>
说明:可以看到最后一组按钮中有data-Method="addScaleX"或data-Method="addScaleY",这需要修改cropper.js的源码,添加addScaleX,addScaleY方法.
在cropper.js中找到scaleX,scaleY方法,在其后面分别添加这两个方法(分别用于在水平、垂直方向拉伸原图):
/**
* add scaleX of the image
*
* @param {Number} addNumber
*
* @param {Number} decimalCount
*
* @param {Number} maxABS
*
*/
addScaleX:function addScaleX(addNumber,decimalCount,maxABS){
var self = this;
var scaleX = self.image.scaleX;
scaleX+=addNumber;
if(decimalCount&&!isNaN(decimalCount)){
scaleX=scaleX.toFixed(parseInt(decimalCount));
}
if(scaleX>Math.abs(maxABS)||scaleX<-Math.abs(maxABS)){
return;
}
this.scaleX(scaleX);
},
/**
* add scaleY of the image
*
* @param {Number} addNumber
*
* @param {Number} decimalCount
*
* @param {Number} maxABS
*
*/
addScaleY:function addScaleY(addNumber,decimalCount,maxABS){
var self = this;
var scaleY = self.image.scaleY;
scaleY+=addNumber;
if(decimalCount&&!isNaN(decimalCount)){
scaleY=scaleY.toFixed(parseInt(decimalCount));
}
if(scaleY>Math.abs(maxABS)||scaleY<-Math.abs(maxABS)){
return;
}
this.scaleY(scaleY);
},
2、js
$("a.editPhoto").on("click",function(){
layer.closeAll();
layer.open({
type : 1,
title : false,
closeBtn : 1,
shift : 2,
shade : 0.01,
shadeClose : false,
area : ['600px','600px'],
content : $("#editPhotoDialog"),
btn : [ '确认', '取消' ],
yes : function(index) { // 确认按钮
if($("#image").attr("src")==""){
layer.msg("未选择图片文件", {
time : 1000
});
return;
}
var cropperData=$("#image").cropper("getData");
var fd=new FormData();
fd.append("file",$("#image").data("file"));
fd.append("scaleX",cropperData.scaleX);
fd.append("scaleY",cropperData.scaleY);
fd.append("rotate",parseInt(cropperData.rotate));
fd.append("x",parseInt(cropperData.x));
fd.append("y",parseInt(cropperData.y));
fd.append("width",parseInt(cropperData.width));
fd.append("height",parseInt(cropperData.height));
var loadIndex=0;
$.ajax({
url : "../../user/webSetPersonalPhoto",//设置个人头像接口
type: 'post',
data: fd,
dataType: 'json',
cache: false,
processData: false,
contentType: false,
beforeSend: function(){
layer.close(index);
loadIndex = layer.load(1);
},
success:function(data, status, xhr, $form) {
layer.msg(data.msg, {
time : 1000
});
$("#header .userinfo div").css({//刷新个人头像
"background-image" : "url(../../user/getPersonalPhoto?_="+ new Date().getTime()+ ")"
});
},
complete : function(xhr, status, $form) {
layer.close(loadIndex);
if (status == "parsererror") {
location.reload(true);// 刷新浏览器,类似于按F5
}
}
});
},
end : function(index) {
$("#image").cropper("destroy").attr("src","").data("file",null);
}
});
});
$(".btn-group").on('click', '[data-method]', function () {
var $this = $(this);
var data = $this.data();
var $target;
var result;
if ($this.prop('disabled') || $this.hasClass('disabled')) {
return;
}
if ($("#image").data('cropper') && data.method) {
data = $.extend({}, data); // Clone a new one
if (typeof data.target !== 'undefined') {
$target = $(data.target);
if (typeof data.option === 'undefined') {
try {
data.option = JSON.parse($target.val());
} catch (e) {
console.log(e.message);
}
}
}
if (data.method === 'rotate') {
$("#image").cropper('clear');
}
if(data.method === 'addScaleX'||data.method === 'addScaleY'){
result = $("#image").cropper(data.method, data.option, data.secondOption,data.threeOption);
}else{
result = $("#image").cropper(data.method, data.option, data.secondOption);
}
if (data.method === 'rotate') {
$("#image").cropper('crop');
}
if ($.isPlainObject(result) && $target) {
try {
$target.val(JSON.stringify(result));
} catch (e) {
console.log(e.message);
}
}
}
});
var URL = window.URL || window.webkitURL;
var uploadedImageURL;
if (URL) {
$('#inputImage').change(function (e) {
var files = this.files;
var file;
if (files && files.length) {
file = files[0];
var errorMsg="";
if (!/^image\/\w+$/.test(file.type)) {
errorMsg="请选择图片文件";
}else if(file.size==0){
errorMsg="图片为空,请重新选择";
}else if(file.size>2048000){
errorMsg="图片大小超过最大限制(2MB)";
}
if(errorMsg!=""){
$("#inputImage").val("");
layer.msg(errorMsg,{time:1000});
return;
}
if (uploadedImageURL) {
URL.revokeObjectURL(uploadedImageURL);
}
uploadedImageURL = URL.createObjectURL(file);
$("#image").cropper("destroy").attr('src', uploadedImageURL).data('file',file).cropper({
aspectRatio: 1 / 1,
dragMode:"move",
toggleDragModeOnDblclick:false,
strict:true,
minCanvasWidth: 50,//画布
minCanvasHeight: 0,
minCropBoxWidth: 50,//裁剪框
minCropBoxHeight: 0,
minContainerWidth: 50,//容器
minContainerHeight: 50,
/*viewMode:2,*/
preview: '.img-preview',
crop: function (e) {
}
});
$("#inputImage").val("");
}
});
} else {
$('#inputImage').prop('disabled', true).parent().addClass('disabled');
}
说明:以上代码中使用的cropper版本是Cropper v3.0.0-beta,下载地址:https://github.com/fengyuanchen/cropper;
js部分使用的是FormData提交文件即裁剪旋转数据(因input file选择文件时再单击'取消'(而不是'打开')后file就没有了,造成不好的体验).
3、css/* Basic */
/* Main
* ========================================================================== */
/* Icons
* -------------------------------------------------------------------------- */
.icon {
display: inline-block;
width: 20px;
height: 20px;
background-image: url("../assets/img/icons.png");
vertical-align: middle;
}
.icon-move {
background-position: 0 0;
}
.icon-crop {
background-position: -30px 0;
}
.icon-zoom-in {
background-position: -60px 0;
}
.icon-zoom-out {
background-position: -90px 0;
}
.icon-rotate-left {
background-position: -120px 0;
}
.icon-rotate-right {
background-position: -150px 0;
}
.icon-lock {
background-position: -180px 0;
}
.icon-unlock {
background-position: -210px 0;
}
.icon-remove {
background-position: -240px 0;
}
.icon-refresh {
background-position: -270px 0;
}
.icon-upload {
background-position: -300px 0;
}
.icon-off {
background-position: -330px 0;
}
.icon-info {
background-position: -360px 0;
}
/* Alerts
* -------------------------------------------------------------------------- */
.docs-alert {
display: none;
position: fixed;
top: 20px;
left: 0;
right: 0;
height: 0;
text-align: center;
opacity: 0.9;
}
.docs-alert .message {
display: inline-block;
padding: 5px 10px;
border-radius: 2px;
background-color: #aaa;
color: #fff;
}
.docs-alert .primary {
background-color: #0074d9;
}
.docs-alert .success {
background-color: #2ecc40;
}
.docs-alert .info {
background-color: #39cccc;
}
.docs-alert .warning {
background-color: #ff851b;
}
.docs-alert .danger {
background-color: #ff4136;
}
/* Button
* -------------------------------------------------------------------------- */
.btn-primary {
border-color: #003973; /* hsb(210, 100%, 45%) */
background-color: #00468c; /* hsb(210, 100%, 55%) */
}
.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active,
.btn-primary.active,
.btn-primary.active:focus,
.btn-primary.active:hover {
border-color: #00264d; /* hsb(208, 100%, 10%) */
background-color: #003366; /* hsb(208, 100%, 40%) */
}
/* Basic style
* -------------------------------------------------------------------------- */
body {
overflow-x: hidden;
}
/* Header */
.docs-header {
border-color: #003973;
background-color: #00468c;
color: #fff;
}
.docs-header .navbar-brand {
color: #eee;
}
.docs-header .navbar-toggle {
border-color: #003973;
background-color: #00468c;
}
.docs-header .navbar-toggle:hover,
.docs-header .navbar-toggle:focus {
border-color: #003366;
background-color: #003973;
}
.docs-header .navbar-collapse {
border-color: #003973;
}
.docs-header .navbar-text {
color: #ddd;
}
.docs-header .navbar-nav > li > a {
color: #eee;
}
/* Content */
.img-container,
.img-preview {
background-color: #f7f7f7;
overflow: hidden;
width: 100%;
text-align: center;
}
.img-container {
min-height: 200px;
max-height: 390px;
margin-bottom: 20px;
}
@media (min-width: 768px) {
.img-container {
min-height: 390px;
}
}
.img-container > img {
max-width: 100%;
}
.docs-preview {
margin-left: 15px;
margin-bottom: 10px;
}
.img-preview {
float: left;
margin-right: 10px;
margin-bottom: 10px;
border: 1px solid grey;
}
.img-preview > img {
max-width: 100%;
}
.preview-lg {
width: 148px !important;
height: 148px !important;
}
.preview-md {
width: 78px !important;
height: 78px !important;
}
.preview-sm {
width: 39px !important;
height: 39px !important;
}
.preview-xs {
width: 25px !important;
height: 25px !important;
margin-right: 0;
}
.docs-data > .input-group {
margin-bottom: 10px;
}
.docs-data > .input-group > label {
min-width: 80px;
}
.docs-data > .input-group > span {
min-width: 50px;
}
.docs-buttons > .btn,
.docs-buttons > .btn-group,
.docs-buttons > .form-control {
margin-right: 5px;
margin-bottom: 10px;
}
.docs-toggles > .btn,
.docs-toggles > .btn-group,
.docs-toggles > .dropdown {
margin-bottom: 10px;
}
.docs-tooltip {
display: block;
margin: -6px -12px;
padding: 6px 12px;
}
.docs-tooltip > .icon {
margin: 0 -3px;
vertical-align: middle;
}
.tooltip-inner {
white-space: normal;
}
.btn-upload .tooltip-inner {
white-space: nowrap;
}
@media (max-width: 400px) {
.btn-group-crop {
margin-right: -15px!important;
}
.btn-group-crop > .btn {
padding-left: 5px;
padding-right: 5px;
}
.btn-group-crop .docs-tooltip {
margin-left: -5px;
margin-right: -5px;
padding-left: 5px;
padding-right: 5px;
}
}
.docs-options .dropdown-menu {
width: 100%;
}
.docs-options .dropdown-menu > li {
padding: 3px 20px;
}
.docs-options .dropdown-menu > li:hover {
background-color: #f7f7f7;
}
.docs-options .dropdown-menu > li > label {
display: block;
}
.docs-cropped .modal-body {
text-align: center;
}
.docs-cropped .modal-body > img,
.docs-cropped .modal-body > canvas {
max-width: 100%;
}
三、后台部分代码:
1、后台用的是spring的MultipartFile、Spring这部分的配置大致如下:
<!-- file uploader support -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8" />
<property name="maxUploadSize" value="255541538" />
</bean>
2、后台接口:(这里图片是以二进制流的形式存在数据库中的、请酌情修改)
/** 设置个人头像
* @param scaleX 裁剪参数scaleX
* @param scaleY 裁剪参数scaleY
* @param rotate 裁剪参数rotate
* @param x 裁剪参数x
* @param y 裁剪参数y
* @param width 裁剪参数width
* @param height 裁剪参数height
* @param file 图片文件
* @return
*/
@RequestMapping(value = "/webSetPersonalPhoto", method = RequestMethod.POST)
@ResponseBody
public Tidings<User> webSetPersonalPhoto(
@RequestParam("scaleX") Double scaleX,
@RequestParam("scaleY") Double scaleY,
@RequestParam("rotate") Integer rotate,
@RequestParam("x") Integer x,
@RequestParam("y") Integer y,
@RequestParam("width") Integer width,
@RequestParam("height") Integer height,
@RequestParam("file") MultipartFile file) {
String fileName=file.getOriginalFilename().toLowerCase();
String imageType=fileName.substring(fileName.lastIndexOf(".")+1);
if (!fileName.matches(".*\\.(jpg|jpeg|png|gif|bmp)")) {
return new Tidings<User>("failure", "请选择图片文件");
}
//初始化裁剪信息
Cropper cropper=new Cropper(scaleX,scaleY,rotate, x, y, width, height);
//设置目标图片宽度
cropper.setFactWidth(512);
Subject subject = SecurityUtils.getSubject();
String username = (String) subject.getPrincipal();
InputStream input;
byte[] photo = null;
try {
input = file.getInputStream();
photo=cropper.rotate_CropImage(input, imageType);
input.close();
} catch (IOException e) {
e.printStackTrace();
}
User user=userServiceImpl.findByUsername(username);
if (photo != null && this.userServiceImpl.updatePropByUsername(username, "personalPhoto", photo)) {
return new Tidings<User>("success", "设置个人头像成功",user);
} else {
return new Tidings<User>("failure", "设置个人头像失败",user);
}
}
上面的SecurityUtils、Subject是Shiro权限框架中的东西,Tidings是封装返回结果的类.请酌情修改部分代码.
附:
1、Tiddings.java:
public class Tidings<T> {
private String status;
private String msg;
private T t;
public Tidings(){
super();
}
public Tidings(String status,String msg){
super();
this.status=status;
this.msg=msg;
}
public Tidings(String status,String msg,T t){
super();
this.status=status;
this.msg=msg;
this.t=t;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
2、获取个人头像:
/**
* 获取个人头像
*
* @param request
* @param response
*/
@RequestMapping(value = "/getPersonalPhoto", method = RequestMethod.GET)
public void getPersonalPhoto(HttpServletRequest request, HttpServletResponse response) {
Subject subject = SecurityUtils.getSubject();
String username = (String) subject.getPrincipal();
User user = this.userServiceImpl.findByUsername(username);
byte[] b = user.getPersonalPhoto();
if (b == null) {//未设置图片则用一张默认图片
FileInputStream fis = null;
try {
fis = new FileInputStream(
request.getSession().getServletContext().getRealPath("/") + "img/default_personalPhoto.png");
b = new byte[fis.available()];
fis.read(b);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
response.setContentType("image/png");
OutputStream out = null;
try {
out = response.getOutputStream();
out.write(b);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}