文档章节

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

l
 luckxz999
发布于 2016/06/20 17:39
字数 2071
阅读 254
收藏 2

第一步:引入相关文件

jQuery主文件:
<script src="jquery-1.9.1.min.js" type="text/javascript"></script>
Jcrop主文件
<script src="jquery.Jcrop.js" type="text/javascript"></script>
<link rel="stylesheet" href="jquery.Jcrop.css" type="text/css" />

文件异步上传JS,用于不刷新页面上传图片
<script src="ajaxfileupload.js" type="text/javascript"></script>

第二步:图片处理流程及HTML页面组织
处理流程如下:先把原图异步上传(ajaxFileUpload)至服务器某临时目录(我是放在tomcat的webapps某目录下,方便删除),保证该原图可以通过http访问到;
将该原图展示在页面上,通过jcrop进行裁剪,点击“裁剪上传”按钮,把裁剪的尺寸信息提交给后台,后台程序根据裁剪的尺寸及原图(webapps某目录下)进行图片的裁剪(ImageReader和Rectangle等);
裁剪后的图片上传至图片服务器,原图(webapps某目录下)删除。
图片上传输入框:
<input type="file" name="img_poster" id="img_poster" onchange="ajaxFileUpload()"/>
裁剪框:
<div class="cutDiv">
    <p id="cutInfo"></p>
    <img id="img1" alt="" src="" />
    <input type="hidden" id="x1" name="x1" value="0" />
    <input type="hidden" id="y1" name="y1" value="0" />
    <input type="hidden" id="x2" name="x2" value="0" />
    <input type="hidden" id="y2" name="y2" value="0" />
    <input type="hidden" id="cw" name="cw" value="0" />
    <input type="hidden" id="ch" name="ch" value="0" />
    <input type="hidden" id="imgName" name="imgName" value="" />
    <input type="hidden" id="imgType" name="imgType" value="" />
    <input id="cutimg" type="button" value="裁剪上传" />
    <input id="cancelimg" type="button" value="取消" />
</div>


第三步:js代码初始化 
<script type="text/javascript">
   var _jcropApi, _boundx, _boundy, _ratio=1;//定义比例、长宽等
   $(document).ready(function() {   
      //取消按钮事件   
      $("#cancelimg").click(function() {
         $("#img_hotLine").attr('value','');
         $(".img-group").show();
         $("#cutDiv").hide();

         if (_jcropApi) {
             _jcropApi.destroy();
         }
         $("#img1").hide();

      });
      //裁剪上传按钮事件
      $("#cutimg").click(function() {
        ajaxFileCut();
      });        
_ratio = 1;
     //当裁剪框变动时,将左上角相对图片的X坐标与Y坐标,宽度以及高度放到<input type="hidden">中    (上传到服务器上裁剪会用到)
     function showCoords(c) {
       $('#x1').val(c.x * _ratio);
       $('#y1').val(c.y * _ratio);
       $('#x2').val(c.x2 * _ratio);
       $('#y2').val(c.y2 * _ratio);
       $('#cw').val(c.w * _ratio);
       $('#ch').val(c.h * _ratio);
       $("#cutInfo").text("已选择宽*高:" + (parseInt($('#x2').val()) - parseInt($('#x1').val())) + "*" + (parseInt($('#y2').val()) - parseInt($('#y1').val())));
     }
   });
第四步:异步图片上传代码
//当AJAX上传图片操作
function ajaxFileUpload() {
   $.ajaxFileUpload
   (
      {
         url: '/ajaxImageUpload', //用于文件上传的服务器端请求地址
         secureuri: false, //一般设置为false,是否安全上传
         fileElementId: 'img_poster', //文件上传控件的id属性  <input type="file" id="file" name="file" />
         dataType: 'json', //返回值类型 一般设置为json 期望服务器传回的数据类型
         success: function (data, status)  //服务器成功响应处理函数
         {
            var result = data.result;
            if (result && result == "success") {
               $("#cutDiv").show();//显示裁剪框
               var _imgTemp = new Image();
               _imgTemp.src = "http://localhost/images/" + data.img_urls;
               _imgTemp.onload = function() {
                  //上传成功后在将服务器上刚刚上传的图片显示在img1上
                  $("#img1").attr("src", "http://localhost/images/" + data.img_urls).show();
                  $("#imgName").val(data.img_urls);
                  //同时启动裁剪操作,触发裁剪框显示,让用户选择图片区域
                  $("#img1").Jcrop({
                     aspectRatio: 2 / 1,
                     bgOpacity: .4,     
                     fadeTime: 10,
                     boxWidth: 500,
                     boxHeight: 500,
                     onChange: showCoords,   //当裁剪框变动时执行的函数
                     onSelect: showCoords   //当选择完成时执行的函数
                  }, function() {
                     _jcropApi = this;
                     _jcropApi.focus();
                     var bounds = this.getBounds();
                     _boundx = bounds[0];
                     _boundy = bounds[1];
                     _jcropApi.setImage("${ctximages}" + data.img_urls);
                     _jcropApi.animateTo([0, 0, 320, 160]);
                     _jcropApi.setOptions({allowSelect: false});
                     _jcropApi.setOptions({
                        minSize: [320, 160]
                     });
                  });
               }
            } else {
               if (typeof (data.error) != 'undefined') {
                  if (data.error != '') {
                     alert(data.error);
                  } else {
                     alert(data.msg);
                  }
               }
            }
         },
         error: function (data, status, e)//服务器响应失败处理函数
         {
            
            alert("系统错误:请检查图片尺寸及大小是否符合要求");
         }
      }
   )
   return false;
}

第五步:原图异步上传后台处理

/**
 * 异步上传源图片
 * @param request 请求
 * @param response 响应
 */
@ResponseBody
@RequestMapping(value = "/ajaxImageUpload")
public void ajaxImageUpload(HttpServletRequest request, HttpServletResponse response) {
    response.setContentType("application/json; charset=UTF-8");
    Map<String, String> result = new HashMap<>();
    try {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        if (fileMap != null && fileMap.size() > 0) {
            String img_urls = "";
            Map.Entry<String, MultipartFile> entity = fileMap.entrySet().iterator().next();
            // 上传文件名key对应from表单中的name值, value即为上传的文件
            MultipartFile img_cover = entity.getValue();

            String fileName = img_cover.getOriginalFilename();
            // 获取文件扩展名
            String ext = fileName.substring(fileName.lastIndexOf(".") + 1);
            //如果文件不是图片,则不上传
            if (!"jpg".equalsIgnoreCase(ext) && !"jpeg".equalsIgnoreCase(ext)
                    && !"png".equalsIgnoreCase(ext) && !"gif".equalsIgnoreCase(ext)
                    && !"bmp".equalsIgnoreCase(ext)) {
                throw new Exception("文件格式错误");
            }

            if (img_cover.getSize() > 0) {
                String pc_img_url = uploadImageToWebServer(request, img_cover);//上传图片至本机tomcat的webapps目录下,返回图片名称
                if (StringUtils.isNotBlank(pc_img_url)) {
                    img_urls += pc_img_url + ConstUtils.SPLIT_CHAR;
                }
            }
            if (img_urls.length() > 0) {
                img_urls = img_urls.substring(0, img_urls.length() - 1);
            }
            result.put("result", "success");
            result.put("img_urls", img_urls);
        } else {
            throw new Exception("请选择要上传的文件");
        }
    } catch (Exception e) {
        e.printStackTrace();
        result.put("result", "fail");
        result.put("error", "文件上传失败:" + e.getMessage());
    }
    try {
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write(JsonMapper.getInstance().toJson(result));
    }catch (IOException e) {
        logger.error(e.getMessage(), e);
    }
}

第六步:裁剪上传JS

//AJAX上传图片裁剪
function ajaxFileCut() {
   $.ajax({
      type: "get",
      url: "/ajaxImageCut",
      data: 'imgName=' + $("#imgName").val() + '&x1='+$("#x1").val() + "&y1="+$("#y1").val() + "&cw="+$("#cw").val() + "&ch="+$("#ch").val(),
      datatype: "json",
      success: function (data) {
         if (data && data.result) {
            if (data.result == "success") {
               $(".img-group").show();
               $("#cutDiv").hide();
               $("#img1").hide();
               if (_jcropApi) {
                  _jcropApi.destroy();
               }
               //TODO 此处客户端自行控制显示后台返回的裁剪后的图片地址
data.img_url
            } else {
               if (typeof (data.error) != 'undefined') {
                  if (data.error != '') {
                     alert(data.error);
                  } else {
                     alert(data.msg);
                  }
               }
            }
         }
      },
      error: function (data, status, e)//服务器响应失败处理函数
      {
         alert(e);
      }
   });
   return false;
}

第七步:裁剪后台处理

/**
 * 裁剪图片,原图片已上传至工程部署目录的images文件夹下
 * @param request 请求
 * @param response 响应
 * @param imgName 要裁剪的图片名称,即临时保存在webapps下的图片名称
 * @param x1 起始点x坐标
 * @param y1 起始点y坐标
 * @param cw 裁剪后的宽度
 * @param ch 裁剪后的高度
 */
@ResponseBody
@RequestMapping(value = "/ajaxImageCut")
public void ajaxImageCut(HttpServletRequest request, HttpServletResponse response, String imgName, Double x1, Double y1, Double cw, Double ch) {
    Map<String, String> result = new HashMap<>();
    try {
        if (StringUtils.isNotBlank(imgName)) {
            String img_url = cutImage(request, imgType, imgName, x1 == null ? 0 : x1.intValue(),
                    y1 == null ? 0 : y1.intValue(), cw == null ? 0 : cw.intValue(), ch == null ? 0 : ch.intValue(), 0, 0);
            if (StringUtils.isBlank(img_url)) {
                throw new Exception("请确认图片格式及尺寸是否正确");
            }
            result.put("result", "success");
            result.put("img_url", img_url);
        } else {
            throw new Exception("请选择要裁剪的文件");
        }
    } catch (Exception e) {
        e.printStackTrace();
        result.put("result", "fail");
        result.put("error", "文件裁剪失败:" + e.getMessage());
    }
    try {
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(JsonMapper.getInstance().toJson(result));
    }catch (IOException e) {
        logger.error(e.getMessage(), e);
    }
}

附录:图片裁剪代码参考

private File file = null; // 文件对象
private String inputDir; // 输入图路径
private String outputDir; // 输出图路径
private String inputFileName; // 输入图文件名
private String outputFileName; // 输出图文件名
private int outputWidth = 100; // 默认输出图片宽
private int outputHeight = 100; // 默认输出图片高
private boolean proportion = true; // 是否等比缩放标记(默认为等比缩放)
private boolean enlarge = false;//是否放大图片(默认否)
// ===剪切点x y坐标
private int x;
private int y;
/** 对图片裁剪,并把裁剪完的新图片保存 */
    private boolean cut(){
        FileInputStream is = null;
        ImageInputStream iis = null;
        try {
            File file = new File(inputDir + inputFileName);
            Image image = ImageIO.read(file);
            int width = image.getWidth(null);
            int height = image.getHeight(null);
            //如果裁剪尺寸大于原图尺寸,则不裁剪
            if (width <= outputWidth && height <= outputHeight) {
                FileUtils.copyFileCover(inputDir + inputFileName, outputDir + outputFileName, true);
                return true;
            }

            // 读取图片文件
            is = new FileInputStream(inputDir + inputFileName);
            String ext = inputFileName.substring(inputFileName.lastIndexOf(".") + 1);
            /*
             * 返回包含所有当前已注册 ImageReader 的 Iterator,这些 ImageReader 声称能够解码指定格式。
             * 参数:formatName - 包含非正式格式名称 . (例如 "jpeg" 或 "tiff")等 。
             */
            Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName(ext.toLowerCase());
//            if (it.next() == null) {
//                return false;
//            }
            ImageReader reader = it.next();
            // 获取图片流
            iis = ImageIO.createImageInputStream(is);
            /*
             * <p>iis:读取源.true:只向前搜索 </p>.将它标记为 ‘只向前搜索’。
             * 此设置意味着包含在输入源中的图像将只按顺序读取,可能允许 reader 避免缓存包含与以前已经读取的图像关联的数据的那些输入部分。
             */
            reader.setInput(iis, true);
            /*
             * <p>描述如何对流进行解码的类<p>.用于指定如何在输入时从 Java Image I/O
             * 框架的上下文中的流转换一幅图像或一组图像。用于特定图像格式的插件 将从其 ImageReader 实现的
             * getDefaultReadParam 方法中返回 ImageReadParam 的实例。
             */
            ImageReadParam param = reader.getDefaultReadParam();
            /*
             * 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域,通过 Rectangle 对象
             * 的左上顶点的坐标(x,y)、宽度和高度可以定义这个区域。
             */
            Rectangle rect = new Rectangle(x, y, outputWidth, outputHeight);
            // 提供一个 BufferedImage,将其用作解码像素数据的目标。
            param.setSourceRegion(rect);
            /*
             * 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象,并将 它作为一个完整的
             * BufferedImage 返回。
             */
            BufferedImage bi = reader.read(0, param);
            // 保存新图片
            ImageIO.write(bi, ext.toLowerCase(), new File(outputDir + outputFileName));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (iis != null) {
                try {
                    iis.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return false;
    }
 

© 著作权归作者所有

共有 人打赏支持
l
粉丝 0
博文 5
码字总数 8084
作品 0
商丘
基于cropper.js的图片上传和裁剪

项目中要求图片上传并裁剪的功能,之前也有接触过很多图片裁剪插件,效果体验不是很好,今天推荐一款好用的插件-cropper,超级好用,裁剪功能丰富,满足了各种需求。 功能: 1:点击选择图片...

祈澈姑娘
05/17
0
0
微信小程序 - 后台接入七牛云上传图片和视频

在后台上传资源文件过程中,一般都是上传到自己的远程 Linux 服务器上,如果自己不想搭建自己的静态资服务器,我们可以使用七牛云服务器,在这里我们不讨论七牛云的优劣,只分享讨论它的使用...

几个栗子
10/14
0
0
多图片文件上传实现并通过 PostMan 测试

项目的框架是springCloud 的一个服务,图片上传实际上就是用java的IO 流进行读写文件,给后台传递一个路径,后台通过浏览器链接到前端,将前端的图片数据拷贝的服务器的存储地址。 1. 服务端...

kuchawyz
09/27
0
0
求教:使用Java 压缩图片后 图片变得不正常了

开发环境 :windows, myeclipse ,JDK1.7+ 前言: 一个小电商的网站, 由于管理员上上传的图片较大,所以需要后台对已经上传的图片进行一次压缩,但是在压缩过程真遇到了问题, 先看一下导致...

老飞的天空
07/29
0
0
小帅一点资讯版本更新,增加图片转字符图片功能

Java语言实现图片转字符图片 功能需要用到的工具类代码 https://gitee.com/xshuai/ai/blob/master/AIDemo/src/main/java/com/xs/util/image/AnimatedGifEncoder.java https://gitee.com/xsh......

小帅帅丶
08/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

误删除innodb ibdata数据文件恢复

今天在群里看到有人说不熟悉innodb把ibdata(数据文件)和ib_logfile(事务日志)文件误删除了。不知道怎么解决。当时我也不知道怎么办。后来查阅相关资料。终找到解决方法。其实恢复也挺简单...

IT--小哥
15分钟前
0
0
常见设计模式UML图

常见设计模式UML图 本文主要总结常见的设计模式的UML图,方便查阅和思考。 创建型模式 简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式和单例模式,这五种设计模式主要处理对象的创建...

陶小陶
33分钟前
0
0
分布式缓存架构设计

零、 题记 在高并发场景下,需要通过缓存来减少数据库的压力,使得大量的访问进来能够命中缓存,只有少量的需要到数据库层。由于缓存基于内存,可支持的并发量远远大于基于硬盘的数据库。所以...

Ala6
34分钟前
2
0
简单工厂模式

简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。 简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一...

NinjaFrog
36分钟前
1
0
git(一) 基本操作(branch、tag、冲突)

layout: blog istop: true title: "git基本操作(branch、tag、冲突)" date: 2018-09-11 category: 版本控制 tags: - 版本控制 撤销操作 修改最后一次提交 解释:修改上次提交。可以修改内容...

开心的哈士奇
39分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部