jquery.Jcrop结合JAVA后台实现图片裁剪上传实例


Posted in Javascript onNovember 05, 2016

本文介绍了头像裁剪上传功能,用到的技术有  jQuery,springmvc,裁剪插件用的是jcrop(中间遇到很多坑,最终跨越)。

图片上传步骤:

1.用户选择图片

2.将图片传入后台:用户选择图片的时候选择的是各种各样的,但是我们的网页显示图片大小是有限的,所以我们就要在用户选择图片之后将图片添加到后台进行压缩,压缩成我们想要的大小,之后再显示到页面才好

3.利用jcrop裁剪工具对图片进行裁剪并且实时预览

4.点击确定按钮将裁剪用到的参数传入后台,后台图片进行剪切,之后缩放成我们需要的格式

5.最后将图片路径传到前台进行展示

前台页面代码为:

<script src="js-jcrop/jquery.min.js"></script> 
<script src="js-jcrop/jquery.Jcrop.js"></script> 
<script src="js/jquery-form.js"></script> 
<link rel="stylesheet" href="../css/jquery.Jcrop.css" type="text/css" /> 
<style type="text/css"> 
/* 控制预览区域大小*/ 
#preview-pane .preview-container { 
 width: 110px; 
 height: 110px; 
 overflow: hidden; 
} 
#targetDiv{ 
 width: 400px; 
 height: 400px; 
 background-color:#f7fdff; 
} 
</style> 
 
<dl class="dialogBox D_uploadLogo"> 
  <dt class="dialogHeader"> 
    <span class="title">头像上传</span> 
  </dt> 
   
  <dd class="dialogBody"> 
    <dl class="bisinessLogo"> 
      <dt class="title">预览</dt> 
      <dd class="img"> 
        <div id="preview-pane"> 
          <div class="preview-container"> 
           <img src="" id="target2" class="jcrop-preview" alt="未选择图片" /> 
          </div> 
         </div> 
      </dd> 
      <dd class="tc">尺寸:110*110px</dd> 
    </dl> 
    <dl class="bisinessInfo"> 
      <dt class="btnBox02"> 
        <form id="fileUp" action="/file/img/upload" method="post" enctype="multipart/form-data" target="ifm"> 
          <a class="btnGray" href="javascript:;"> 
            <span class="text" id="format">选择图片</span>  
            <b class="bgR"></b> 
            <input type="file" id="file_upload" class="inputFile" name="userphoto"/> 
            <input type="hidden" id="w" name="w"/> 
            <input type="hidden" id="h" name="h"/> 
            <input type="hidden" id="x" name="x"/> 
            <input type="hidden" id="y" name="y"/> 
          </a> 
        </form> 
      </dt> 
      <dd class="info"> 
       
        请从本地选择一张照片,支持jpg,png格式  <span id="msg"></span> 
        <div id="targetDiv"> 
          <img src="" id="target" width="400" height="400" alt="未选择图片"/> 
        </div> 
      </dd> 
    </dl> 
  </dd> 
  <input type="hidden" id="filePathInput" value=""/> 
 
  <dd class="dialogBottom"> 
    <a class="btnBlue btn_confirm" href="javascript:;" onclick="photoSummit();"><span class="text">确定</span><b class="bgR"></b></a> 
    <a class="btnGray btn_cancel" href="javascript:;" onclick="hideDialog();"><span class="text">取消</span><b class="bgR"></b></a> 
  </dd> 
</dl>

1.选择图片

<img src="" id="target" width="400" height="400" alt="未选择图片"/>

2.提交:首先大家知道文件上传的时候用到的标签为:<input type="file"/>   但是有时候我们需要用ajax提交文件并且异步提交,我们如果是用form表单提交的话就不是异步,这样我们回到页面就刷新页面,非常的不方便,但是现在ajax还不能支持文件提交的方式,这时候我们就用到了jquery-form.js,这个文件支持我们用ajax提交文件,代码为:

$("#fileUp").<span style="color:#ff0000;">ajaxSubmit</span>({ 
      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 { 
<span style="white-space:pre">  </span>ImgEditor imgEditor = new ImgEditor(); 
<span style="white-space:pre">  </span>public String filePathFinal = ""; 
<span style="white-space:pre">  </span>private Logger logger = LoggerFactory.getLogger(FileEditorController.class); 
<span style="white-space:pre">  </span>@RequestMapping(value="/img/cutandscale",method=RequestMethod.POST) 
<span style="white-space:pre">  </span>public @ResponseBody int cutAndscaleimg( 
<span style="white-space:pre">      </span>@RequestParam("w") int w, 
<span style="white-space:pre">      </span>@RequestParam("h") int h, 
<span style="white-space:pre">      </span>@RequestParam("x") int x, 
<span style="white-space:pre">      </span>@RequestParam("y") int y 
<span style="white-space:pre">      </span>){ 
<span style="white-space:pre">    </span>imgEditor.cut(filePathFinal,filePathFinal,x,y,w,h); 
<span style="white-space:pre">    </span>imgEditor.scale(filePathFinal, filePathFinal, 110, 110, false); 
<span style="white-space:pre">    </span>return 1; 
<span style="white-space:pre">  </span>} 
<span style="white-space:pre">  </span> 
<span style="white-space:pre">  </span> 
  @RequestMapping(value="/img/upload",method=RequestMethod.POST) 
  public @ResponseBody Parameters addImage( 
  <span style="white-space:pre">   </span>@RequestParam("userphoto") MultipartFile file, 
  <span style="white-space:pre">   </span>HttpServletRequest request, 
  <span style="white-space:pre">   </span>HttpServletResponse response, 
  <span style="white-space:pre">   </span>HttpSession session 
  <span style="white-space:pre">   </span>){ 
  <span style="white-space:pre"> </span>String filePath = "";  
  <span style="white-space:pre"> </span>try { 
  <span style="white-space:pre">   </span>//上传原图 
<span style="white-space:pre">      </span>filePath = imgEditor.uploadFile(file, request,session); 
<span style="white-space:pre">      </span>filePathFinal = filePath; 
<span style="white-space:pre">      </span>//将图片压缩成指定大小 
<span style="white-space:pre">      </span>imgEditor.zoomImage(filePath,filePath,400,400); 
<span style="white-space:pre">    </span>} catch (IOException e) { 
<span style="white-space:pre">      </span>e.printStackTrace(); 
<span style="white-space:pre">    </span>}  
    logger.info("filePath:" + filePath); 
    Parameters parameter = new Parameters(); 
    parameter.setFileName(imgEditor.getFileName(file,request,session)); 
  <span style="white-space:pre"> </span>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打动了我(太好看了),之后就是导入文件,在我这里,我在页面接收后台返回来的图片路径之后启用jcrop,也就是openJcrop()方法,这样就可以加载jcrop插件了,具体大家想进一步了解这个裁剪工具,请到官网细细的研究,我就不再做过多的谈论了。

大家注意,在这里有个大坑,真的是大坑,就是重新选择图片的时候,被jcrop加载过的img的src是不能被修改的,这个当初卡了我好长时间,被jcrop加载一次jcrop就会生成一个自己的编辑对象(我自己的理解),这时候就和原来的img没有关系了,直到最后细细研究api才找到了一个方法,唯一的方法就是将这个jcrop销毁,就是jcrop_api.destroy(),这个有很大的学问,我就提示一点,就是将jcrop_api声明为全局变量,下面贴出js代码(和上边的html是在一个文件下):

<script type="text/javascript"> 
   
   $(function(){ 
    var jcrop_api; 
   }); 
   
   $("#file_upload").change(function() { 
     $("#msg").text(''); 
     var oFile = $(this)[0].files[0]; 
     //判断上传文件大小 
     if (oFile.size > 1*1024*1024) { 
       $("#msg").text('你选择了太大的文件,请选择一个1M以下的图像文件').css('color','red'); 
       $(this).val(""); 
       return; 
     } 
       
     //判断类型 
     var filepath=$(this).val(); 
     var extStart=filepath.lastIndexOf("."); 
     var ext=filepath.substring(extStart,filepath.length).toUpperCase(); 
     if(ext!=".JPEG"&&ext!=".PNG"&&ext!=".JPG"){ 
      $("#msg").text('请选择一个有效的图像文件(jpg,png是允许的)').css('color','red'); 
        $(this).val(""); 
        return; 
     } 
       
    $("#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传输发生错误!!!"); 
      }  
     }); 
  }); 
   function photoSummit(){ 
    
     //alert($("#w").val()+","+$("#h").val()+","+$("#x").val()+","+$("#y").val()); 
     //$("#fileUp").attr("action", "/file/img/upload").submit(); 
     if($("#w").val()>0 && $("#h").val()>0){ 
      $("#fileUp").ajaxSubmit({ 
        type: "POST", 
        url:"/file/img/cutandscale", 
        dataType: "json", 
        contentType:"application/json",  
        success: function(data){ 
           $("#msg").text('上传头像成功!!!').css('color','red'); 
           //alert($("#filePathInput").val()); 
           window.parent.back($("#filePathInput").val()); 
        },  
        error : function(data) {  
          alert("ajax传输发生错误!!!"); 
        }  
      }); 
     }else{ 
      $("#msg").text('请用鼠标截取图片').css('color','red'); 
     }  
   } 
   //启动jcrop 
  function openJcrop(imgPath){ 
    //启动jcrop支持 
        var boundx,boundy, 
        xsize = $('#preview-pane .preview-container').width(), 
        ysize = $('#preview-pane .preview-container').height(); 
         
        $('#target').Jcrop({ 
         minSize: [110, 110], 
         onChange: updatePreview, 
         onSelect: updatePreview, 
         aspectRatio: xsize / ysize 
        },function(){ 
         // Use the API to get the real image size 
         var bounds = this.getBounds(); 
         boundx = bounds[0]; 
         boundy = bounds[1]; 
         jcrop_api = this; 
        }); 
        jcrop_api.setImage(imgPath); 
        function updatePreview(c) 
        { 
         if (parseInt(c.w) > 0) 
         { 
          var rx = xsize / c.w; 
          var ry = ysize / c.h; 
       
          $('#preview-pane .preview-container img').css({ 
           width: Math.round(rx * boundx) + 'px', 
           height: Math.round(ry * boundy) + 'px', 
           marginLeft: '-' + Math.round(rx * c.x) + 'px', 
           marginTop: '-' + Math.round(ry * c.y) + 'px' 
          }); 
          $("#w").val(c.w); 
          $("#h").val(c.h); 
          $("#x").val(c.x); 
          $("#y").val(c.y); 
         } 
         }; 
  } 
    
    
</script>

这样我们就完成了编辑功能,之后我们点击提交就会将w,h,x,y参数传到后台。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
浅析Js(Jquery)中,字符串与JSON格式互相转换的示例(直接运行实例)
Jul 09 Javascript
javascript正则表达式定义(语法)总结
Jan 08 Javascript
node.js微信公众平台开发教程
Mar 04 Javascript
js实现带农历和八字等信息的日历特效
May 16 Javascript
JavaScript接口的实现三种方式(推荐)
Jun 14 Javascript
Bootstrap实现登录校验表单(带验证码)
Jun 23 Javascript
Angular2开发——组件规划篇
Mar 28 Javascript
jQuery实现简单的滑动导航代码(移动端)
May 22 jQuery
Vue如何基于vue-i18n实现多国语言兼容
Jul 17 Javascript
浅析JavaScript预编译和暗示全局变量
Sep 03 Javascript
javascript实现倒计时提示框
Mar 02 Javascript
GitHub上77.9K的Axios项目有哪些值得借鉴的地方详析
Jun 15 Javascript
JavaScript中绑定事件的三种方式及去除绑定
Nov 05 #Javascript
Ajax与服务器(JSON)通信实例代码
Nov 05 #Javascript
Javascript 普通函数和构造函数的区别
Nov 05 #Javascript
Javascript 函数的四种调用模式
Nov 05 #Javascript
详解利用exif.js解决ios手机上传竖拍照片旋转90度问题
Nov 04 #Javascript
jQuery中 $ 符号的冲突问题及解决方案
Nov 04 #Javascript
JAVA Web实时消息后台服务器推送技术---GoEasy
Nov 04 #Javascript
You might like
怎样在UNIX系统下安装php3
2006/10/09 PHP
php面向对象全攻略 (十五) 多态的应用
2009/09/30 PHP
Ubuntu12下编译安装PHP5.3开发环境
2015/03/27 PHP
Symfony2使用Doctrine进行数据库查询方法实例总结
2016/03/18 PHP
laravel如何开启跨域功能示例详解
2017/08/31 PHP
thinkphp5.0自定义验证规则使用方法
2017/11/16 PHP
PHP获取php,mysql,apche的版本信息及更多服务器信息
2021/03/09 PHP
javascript之AJAX框架使用说明
2010/04/24 Javascript
js图片滚动效果时间可随意设定当鼠标移上去时停止
2014/06/26 Javascript
用js判断是否为360浏览器的实现代码
2015/01/15 Javascript
Hallo.js基于jQuery UI所见即所得的Web编辑器
2016/01/26 Javascript
jQuery实现点击查看大图并以弹框的形式居中
2016/08/08 Javascript
AngularJS学习第一篇 AngularJS基础知识
2017/02/13 Javascript
js 发布订阅模式的实例讲解
2017/09/10 Javascript
JS运动特效之完美运动框架实例分析
2018/01/24 Javascript
微信小程序实现折叠与展开文章功能
2018/06/12 Javascript
微信小程序登录时如何获取input框中的内容
2019/12/04 Javascript
JavaScript canvas仿代码流瀑布
2020/02/10 Javascript
echarts实现获取datazoom的起始值(包括x轴和y轴)
2020/07/20 Javascript
vue缓存之keep-alive的理解和应用详解
2020/11/02 Javascript
Django 实现Admin自动填充当前用户的示例代码
2019/11/18 Python
python怎么判断素数
2020/07/01 Python
HTML5 新旧语法标记对我们有什么好处
2012/12/13 HTML / CSS
澳大利亚在线时尚精品店:Hello Molly
2018/02/26 全球购物
Reebok官方旗舰店:美国知名健身品牌锐步
2019/01/07 全球购物
Spartoo美国:欧洲排名第一的在线时装零售商
2019/12/12 全球购物
台湾7-ELEVEN线上购物中心:7-11
2021/01/21 全球购物
毕业生应聘幼儿园的自荐信
2013/11/20 职场文书
小学评语大全
2014/04/22 职场文书
个人租房协议书(范本)
2014/10/14 职场文书
幼儿园端午节活动总结
2015/05/05 职场文书
音乐课外活动总结
2015/05/09 职场文书
个人借条范本
2015/05/25 职场文书
2016反腐倡廉警示教育心得体会
2016/01/13 职场文书
有关花店创业的计划书模板
2019/08/27 职场文书
Python实现拼音转换
2021/06/07 Python