介绍一款好用的头像上传插件


首先,这款插件是基于前端框架Bootstrap而制作的,要引入Bootstrap所必需的js 以及css, 还有Jquery

        <script src="${APP_PATH}/static/js/jquery-1.11.1.min.js"></script>
	<link href="${APP_PATH}/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
	<script src="${APP_PATH}/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
	<link href="${APP_PATH}/static/imageCut/cropper.min.css" rel="stylesheet">
	<link href="${APP_PATH}/static/imageCut/sitelogo.css" rel="stylesheet">
	<script src="${APP_PATH}/static/imageCut/cropper.min.js"></script>
	<script src="${APP_PATH}/static/imageCut/sitelogo.js"></script>

先简单介绍一下工作原理

1.先选取一张图片

2.前端通过js获取剪裁开始点的坐标,以及选取的图片大小

3.通过Ajax异步上传原始图片,以及剪裁的数据

4.后台通过java图片操作剪取图片

5.返回图片保存的路径,在前端显示


国际惯例,先上几张效果图:



移动选取框获取剪裁数据


点击保存后,后台处理,得到返回的图片地址,显示在前台




nice!

接下来,介绍一下代码:

为了后台方便处理剪裁数据,采用Math.floor()取整

startCropper: function () {
      var _this = this;

      if (this.active) {
        this.$img.cropper('replace', this.url);
      } else {
        this.$img = $('<img src="' + this.url + '">');
        this.$avatarWrapper.empty().html(this.$img);
        this.$img.cropper({
          aspectRatio: 1,
          preview: this.$avatarPreview.selector,
          strict: false,
          crop: function (data) {
            var json = [
                  '{"x":' + Math.floor(data.x),
                  '"y":' + Math.floor(data.y),
                  '"height":' + Math.floor(data.height),
                  '"width":' + Math.floor(data.width),
                  '"rotate":' + data.rotate + '}'
                ].join();

            _this.$avatarData.val(json);
          }
        });

        this.active = true;
      }
    }, 



把文件和数据封装为FormData对象 一起通过ajax请求传给后台(注意里面的这两句设为false)

processData:false,

contentType:false,


ajaxUpload: function () {
      var url = this.$avatarForm.attr('action'),
          data = new FormData(this.$avatarForm[0]),
          _this = this;

      $.ajax(url, {
        headers: {'X-XSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')}, 
        type: 'post',
        data: data,
        /*dataType: 'json',*/
        processData: false,
        contentType: false,

        beforeSend: function () {
          _this.submitStart();
        },

        success: function (data) {
          _this.submitDone(data);
        },

        error: function (XMLHttpRequest, textStatus, errorThrown) {
          _this.submitFail(textStatus || errorThrown);
        },

        complete: function () {
          _this.submitEnd();
        }
      });
    },


当然,前端有验证的

isImageFile: function (file) {
      if (file.type) {
        return /^image\/\w+$/.test(file.type);
      } else {
        return /\.(jpg|jpeg|png|gif)$/.test(file);
      }
    },

否则不给上传,并提示信息

submit: function () {
      if (!this.$avatarSrc.val() && !this.$avatarInput.val()) {
        return false;
      }
      var files = this.$avatarInput.prop('files');
      if(!this.isImageFile(files[0])){
    	  return false;
      }
      if (this.support.formData) {
        this.ajaxUpload();
        return false;
      }
    },


这是ajax请求数据




这里是后台的Controller层处理ajax请求,对图片进行裁剪操作,并且返回一个map对象

里面存有 键为 result ,值为裁剪后的图片地址 的一个键值对

@Controller
public class SomeController {
	@Autowired
	private UserService userService;

	@RequestMapping("changeUserPic")
	@ResponseBody
	public Map<String, String> changeUserPic(HttpServletRequest request,
			@RequestParam("avatar_file") MultipartFile file,
			@RequestParam("avatar_data") String dataStr,HttpSession session) throws IllegalStateException, IOException{
		
		JSONObject data = JSONObject.fromObject(dataStr);
		
		
		int height = (int) data.get("height");
		int width = (int) data.get("width");
		int startX = (int) data.get("x");
		int startY = (int)data.get("y");
		Map<String, String> map = new HashMap<String, String>();
		
		if(!file.isEmpty()&&(height > 0 && width > 0 && startX > 0 && startY > 0)) {
	           //上传文件路径
	           String path = request.getServletContext().getRealPath("/userImageFile/");
	           //上传文件名
	           String filename = file.getOriginalFilename();
	           String fileType = filename.substring(filename.indexOf(".") + 1).toLowerCase();
	           
	           String name = UUID.randomUUID().toString()+ filename.substring(filename.indexOf("."));
	           File filepath = new File(path,name);
	           //判断路径是否存在,如果不存在就创建一个
	           if (!filepath.getParentFile().exists()) { 
	               filepath.getParentFile().mkdirs();
	           }
	           //将上传文件保存到一个目标文件当中
	           String imagepath = path + File.separator + name;
	           System.out.println(imagepath);
	           file.transferTo(new File(imagepath));
	           
	           
	           //开始剪裁
	           ImageUtils test = new ImageUtils();
	           test.input = new FileInputStream(imagepath); 
	           test.out = imagepath; 
	           test.cutImage(fileType,startX, startY, width, height);
	           
	           //更新数据库
	           String picPath = request.getContextPath()+File.separator+"userImageFile"+File.separator+ name;
	           userService.updateUser(session.getAttribute("username").toString(), picPath);
	           session.setAttribute("userPic", picPath);
	   		   map.put("result", picPath);
		}
		//前台做了校验,不能上传空文件
		return map;
	}
	
	
}



ajax请求成功后,接收返回的result (我没有返回message), 并且更新前台数据

submitDone: function (data) {
      if ($.isPlainObject(data)) {
        if (data.result) {
          this.url = data.result;
          if (this.support.datauri || this.uploaded) {
            this.uploaded = false;
            this.cropDone();
          } else {
            this.uploaded = true;
            this.$avatarSrc.val(this.url);
           
            this.startCropper();
          }
          this.$avatarInput.val('');
        } else if (data.message) {
          this.alert(data.message);
        }
      } else {
        this.alert('Failed to response');
      }
    },


这个是对图片的裁剪操作代码

public class ImageUtils {  
	
	public  FileInputStream input = null;
	public  FileOutputStream output = null;
	//输出图片地址
	public  String out = null;
	
	
    
  public  void cutImage(String type,int x,  int y, int width, int height) throws IOException {  
         
      ImageInputStream imageStream = null;  
      try {  
          String imageType=(null==type||"".equals(type))?"jpg":type;  
          Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(imageType);  
          ImageReader reader = readers.next();  
          imageStream = ImageIO.createImageInputStream(input);  
          reader.setInput(imageStream, true);  
          ImageReadParam param = reader.getDefaultReadParam();  
          Rectangle rect = new Rectangle(x, y, width, height);  
          param.setSourceRegion(rect);  
          BufferedImage bi = reader.read(0, param);  
          ImageIO.write(bi, imageType, new File(out)); 
          /*ImageIO.write(bi, imageType, output); */
          /*
           * 假如输出到原图片地址,ImageIO.write(),,第三个参数必须 new File
           * 而不是一个 FileOutputStream对象 ,否则报错
           */
      } finally {  
      	if (input != null )  
      		input.close() ;      
	   if (imageStream != null )  
	    	 imageStream.close();   
          
      }  
  }  
}
	

对了,关于图像旋转后剪裁是会出问题的,因为后台处理的是未旋转的原图片,想要实现旋转的效果,可以根据ajax传递的参数

rotate的值(90,180,270,),来相应的更改起点坐标,小伙伴们可以自己实现



对json数据的操作,我引用的是这个jar包,pom依赖是:

    
            <!-- json所需jar包        注明jdk版本,否则无法下载-->
		<dependency>
		    <groupId>net.sf.json-lib</groupId>
		    <artifactId>json-lib</artifactId>
		    <version>2.4</version>
		    <classifier>jdk15</classifier>  
		</dependency>

哈哈哈!大功告成

想研究一下代码的小伙伴可以到下面这个地址下载

资源地址




                
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值