头像裁剪上传功能,用到的技术有 jquery,springmvc,裁剪插件用的是jcrop(中间遇到很多坑,最终跨越)。由于保密性我不能将别的源码发送到网上,请大家见谅。
图片上传步骤:
1.用户选择图片
2.将图片传入后台:用户选择图片的时候选择的是各种各样的,但是我们的网页显示图片大小是有限的,所以我们就要在用户选择图片之后将图片添加到后台进行压缩,压缩成我们想要的大小,之后再显示到页面才好
3.利用jcrop裁剪工具对图片进行裁剪并且实时预览
4.点击确定按钮将裁剪用到的参数传入后台,后台图片进行剪切,之后缩放成我们需要的格式
5.最后将图片路径传到前台进行展示
前台页面代码为:
1.选择图片
2.提交:首先大家知道文件上传的时候用到的标签为: 但是有时候我们需要用ajax提交文件并且异步提交,我们如果是用form表单提交的话就不是异步,这样我们回到页面就刷新页面,非常的不方便,但是现在ajax还不能支持文件提交的方式,这时候我们就用到了jquery-form.js,这个文件支持我们用ajax提交文件,代码为:
$("#fileUp").ajaxSubmit({
type: "POST",
url:"/file/img/upload",
dataType: "json",
contentType:"application/json",
success: function(parameter){
$("#target2").attr('src','/upload/'+parameter.fileName);
$("#filePathInput").val('/upload/'+parameter.fileName);
if($("#format").text()=="重新上传"){
jcrop_api.destroy()
}
$("#format").text("重新上传");
//启动jcrop支持
openJcrop('/upload/'+parameter.fileName);
},
error : function(data) {
alert("ajax传输发生错误!!!");
}
});
这样就能将文件用ajax的方式提交到后台,注意这里用的是ajaxSubmit,这个方法对应jquery-form.js,后台代码为:
package com.quanshi.ums.gate.view.rest.controllers;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.quanshi.ums.gate.persistence.entities.Parameters;
import com.quanshi.ums.gate.view.rest.ImgEditor;
/**
* 图像上传和修改相关类
* @author kunpeng.zhao
*
*/
@Controller
@RequestMapping(value="/file")
public class FileEditorController {
ImgEditor imgEditor = new ImgEditor();
public String filePathFinal = "";
private Logger logger = LoggerFactory.getLogger(FileEditorController.class);
@RequestMapping(value="/img/cutandscale",method=RequestMethod.POST)
public @ResponseBody int cutAndscaleimg(
@RequestParam("w") int w,
@RequestParam("h") int h,
@RequestParam("x") int x,
@RequestParam("y") int y
){
imgEditor.cut(filePathFinal,filePathFinal,x,y,w,h);
imgEditor.scale(filePathFinal, filePathFinal, 110, 110, false);
return 1;
}
@RequestMapping(value="/img/upload",method=RequestMethod.POST)
public @ResponseBody Parameters addImage(
@RequestParam("userphoto") MultipartFile file,
HttpServletRequest request,
HttpServletResponse response,
HttpSession session
){
String filePath = "";
try {
//上传原图
filePath = imgEditor.uploadFile(file, request,session);
filePathFinal = filePath;
//将图片压缩成指定大小
imgEditor.zoomImage(filePath,filePath,400,400);
} catch (IOException e) {
e.printStackTrace();
}
logger.info("filePath:" + filePath);
Parameters parameter = new Parameters();
parameter.setFileName(imgEditor.getFileName(file,request,session));
return parameter;
}
}
我在这规定图片在前台展示的大小为400*400,用到的图片裁剪压缩等的工具类为:
package com.quanshi.ums.gate.view.rest;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.multipart.MultipartFile;
public class ImgEditor {
/**
* 改变图片尺寸
* @param srcFileName 源图片路径
* @param tagFileName 目的图片路径
* @param width 修改后的宽度
* @param height 修改后的高度
*/
public void zoomImage(String srcFileName,String tagFileName,int width,int height){
try {
BufferedImage bi = ImageIO.read(new File(srcFileName));
BufferedImage tag=new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);
tag.getGraphics().drawImage(bi, 0, 0, width, height, null);
ImageIO.write(tag, "jpg", new File(tagFileName));//画图
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 缩放图像(按高度和宽度缩放)
* @param srcImageFile 源图像文件地址
* @param result 缩放后的图像地址
* @param height 缩放后的高度
* @param width 缩放后的宽度
* @param bb 比例不对时是否需要补白:true为补白; false为不补白;
*/
public void scale(String srcImageFile, String result, int height, int width, boolean bb) {
try {
double ratio = 0.0; // 缩放比例
File f = new File(srcImageFile);
BufferedImage bi = ImageIO.read(f);
Image itemp = bi.getScaledInstance(width, height, bi.SCALE_SMOOTH);
// 计算比例
if ((bi.getHeight() > height) || (bi.getWidth() > width)) {
if (bi.getHeight() > bi.getWidth()) {
ratio = (new Integer(height)).doubleValue()
/ bi.getHeight();
} else {
ratio = (new Integer(width)).doubleValue() / bi.getWidth();
}
AffineTransformOp op = new AffineTransformOp(AffineTransform
.getScaleInstance(ratio, ratio), null);
itemp = op.filter(bi, null);
}
if (bb) {//补白
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, width, height);
if (width == itemp.getWidth(null))
g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2,
itemp.getWidth(null), itemp.getHeight(null),
Color.white, null);
else
g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0,
itemp.getWidth(null), itemp.getHeight(null),
Color.white, null);
g.dispose();
itemp = image;
}
ImageIO.write((BufferedImage) itemp, "JPEG", new File(result));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 图像切割(按指定起点坐标和宽高切割)
* @param srcImageFile 源图像地址
* @param result 切片后的图像地址
* @param x 目标切片起点坐标X
* @param y 目标切片起点坐标Y
* @param width 目标切片宽度
* @param height 目标切片高度
*/
public void cut(String srcImageFile, String result,
int x, int y, int width, int height) {
try {
// 读取源图像
BufferedImage bi = ImageIO.read(new File(srcImageFile));
int srcWidth = bi.getHeight(); // 源图宽度
int srcHeight = bi.getWidth(); // 源图高度
if (srcWidth > 0 && srcHeight > 0) {
Image image = bi.getScaledInstance(srcWidth, srcHeight,
Image.SCALE_DEFAULT);
// 四个参数分别为图像起点坐标和宽高
// 即: CropImageFilter(int x,int y,int width,int height)
ImageFilter cropFilter = new CropImageFilter(x, y, width, height);
Image img = Toolkit.getDefaultToolkit().createImage(
new FilteredImageSource(image.getSource(),
cropFilter));
BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(img, 0, 0, width, height, null); // 绘制切割后的图
g.dispose();
// 输出为文件
ImageIO.write(tag, "JPEG", new File(result));
}
} catch (Exception e) {
e.printStackTrace();
}
}
//获得文件名字
public String getFileName(MultipartFile file, HttpServletRequest request,HttpSession session){
String FILE_PATH = session.getServletContext().getRealPath("/") + "upload";
String fileName = file.getOriginalFilename();
String[] suffixNameArr = fileName.split("\\.");
String suffixName = suffixNameArr[suffixNameArr.length-1];
String userName = SecurityContextHolder.getContext().getAuthentication().getName();
return getTime() + userName+"."+suffixName;
}
//文件上传,返回文件路径
public String uploadFile(MultipartFile file, HttpServletRequest request,HttpSession session) throws IOException {
String FILE_PATH = session.getServletContext().getRealPath("/") + "upload";
String fileName = getFileName(file,request,session);
File tempFile = new File(FILE_PATH, fileName);
if (!tempFile.getParentFile().exists()) {
tempFile.getParentFile().mkdir();
}
if (!tempFile.exists()) {
tempFile.createNewFile();
}
file.transferTo(tempFile); //将上传文件写到服务器上指定的文件。
return FILE_PATH + "\\" + tempFile.getName();
}
/* public static File getFile(String fileName) {
return new File(FILE_PATH, fileName);
} */
public String getTime(){
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//设置日期格式
String nowTime = df.format(date).toString();
return nowTime;
}
}
这样就将图片要裁剪的图片路径返回页面展示
3.之后就是图片裁剪了,图片裁剪功能我找了好多插件,最后锁定jcrop,也是因为它的demo打动了我(太好看了),之后就是导入文件,至于这个裁剪工具具体的运用的话大家请参考这篇博文,当然这是被人写的非常好,还有api可以看,http://blog.csdn.net/xht555/article/details/43407141 在我这里,我在页面接收后台返回来的图片路径之后启用jcrop,也就是openJcrop()方法,这样就可以加载jcrop插件了,具体大家想进一步了解这个裁剪工具,请到官网细细的研究,我就不再做过多的谈论了。
大家注意,在这里有个大坑,真的是大坑,就是重新选择图片的时候,被jcrop加载过的img的src是不能被修改的,这个当初卡了我好长时间,被jcrop加载一次jcrop就会生成一个自己的编辑对象(我自己的理解),这时候就和原来的img没有关系了,直到最后细细研究api才找到了一个方法,唯一的方法就是将这个jcrop销毁,就是jcrop_api.destroy(),这个有很大的学问,我就提示一点,就是将jcrop_api声明为全局变量,下面贴出js代码(和上边的html是在一个文件下):
4.传到后台之后的代码在上面我已经贴出,不做过多解释,大家自己理解,不懂的可以给我留言
整篇博文纯手打,如果大家觉得幼稚的借鉴的地方请给个赞,工作时候抽出时间比较难,但还是谢了这篇博文,如果谁发现bug或者不对的地方请随时联系我,大家互相交流提高。