Jcrop插件+Canvas实现图片上传预览+图片裁剪上传

19 篇文章 0 订阅

前言

想实现一个功能:用户点击上传按钮,选择图片后。图片显示在一个弹出框上,并可以对图片进行裁剪。裁剪后的图片显示在页面上。提交表单即可上传图片。

遇到问题

  1. 浏览器的安全设置不让用户获取上传的图片路径,实际获取的是c:\fakepath\a.jpg(假设图片是c盘下的a.jpg)
  2. ajax如何异步上传图片?
  3. Canvas画裁剪的图片时长宽不一样(本来想画100x100的图片,结果在画布上显示100x50)
  4. Canvas上的图片怎么上传?

问题解决

  1. 选择图片后,触发input的onchange事件:发送异步请求将图片上传,返回图片的名称,然后弹框,将图片显示出来。
  2. 将表单封装为FormData类型,ajax进行一些设置即可,具体百度有说。
  3. 设置Canvas宽高我用的是style:width:100px;height:100px;,后来直接写Canvas的属性width=100px height=100px,问题就解决了。具体原因百度有说。
  4. 获取Canvas的图片流(实际上就是一段字符串),表单提交图片流。后台用Base64解析图片流成为byte数组,然后根据byte数组创建输入流,有了输入流,就能够写出一张图片了。

部分代码

        <!-- 图片上传,openPhotoCut的功能是异步上传图片,显示图片并裁剪 -->
        <form id="uploadForm" class="form-horizontal" role="form" enctype="multipart/form-data">
        <div class="form-group namediv">

            <label class="col-sm-2" for="photo" style="font-size: 15px;"><span style="color:red;">&nbsp;&nbsp;</span>菜品图片</label>
            <div class="col-sm-6">
                <input type="file" class="photo" id="photo" name="photo" onchange="openPhotoCut();" />
            </div>
        </div>
        </form>
    // 打开图片裁剪框
    function openPhotoCut() {
        // ajax上传图片的关键
        var formData = new FormData($("#uploadForm"));
        var fileName;  // 上传文件名
        // 在表单里面添加上传的图片
        formData.append("photo", $(".photo").get(0).files[0]);
        // 上传未裁剪的图片
        $.ajax({
            type: "POST",
            url: "${pageContext.request.contextPath }/business/product/getFileLocationAjax",
            async: false,
            data: formData,
            // 以下两行不写可能会报错
            contentType: false,
            processData: false,
            success: function(result) {
                // 得到图片名称
                fileName = result;
                alert(fileName);
            }
        });
        // 这里使用的是layer弹框插件,弹出图片裁剪框,显示上传的图片,并进行裁剪
        layer.open({
          title: '图片裁剪',
          type: 1,
          skin: 'layui-layer-rim', //加上边框
          area: ['600px', '500px'], //宽高
          // 这里纯粹是html内容,cutAndShow的功能是把刚才上传的图片删除,然后把裁剪的图片显示在Canvas上,并保存图片流在input中。
          content: '<img id="prephoto" src="${pageContext.request.contextPath }/uploads/' + fileName + '"/>' +
            '<button class="btn btn-primary" style="margin: 20px;" onclick="cutAndShow(\'' + fileName + '\');">裁剪</button>' +
            'x轴:<input type="text" readonly id="x" name="x" value="0" style="width: 50px;" /> ' + 
            'y轴:<input type="text" readonly id="y" name="y" value="0" style="width: 50px;" /> ' +
            '长度:<input type="text" readonly id="w" name="w" value="0" style="width: 50px;" /> ' +
            '宽度:<input type="text" readonly id="h" name="h" value="0" style="width: 50px;" /> '
        });
        // 裁剪插件
        $("#prephoto").Jcrop({
            minSize: [ 80, 80 ],  // 最小尺寸
            aspectRatio: 1,  // 等宽高
            onSelect: updateCoords 
        });

    }
    // 及时更新裁剪区域坐标和尺寸
    function updateCoords(c)
    {
       $('#x').val(c.x);
       $('#y').val(c.y);
       $('#w').val(c.w);
      $('#h').val(c.h);
    };
    // 裁剪图片并显示在画布
    function cutAndShow(fileName) {
        // 删除未裁剪的图片
        $.ajax({
            type: "POST",
            url: "${pageContext.request.contextPath }/business/product/deleteImageAjax",
            async: false,
            data: {"fileName": fileName},
            success: function(result) {
            }
        }); 
        var x = $("#x").val();
        var y = $("#y").val();
        var w = $("#w").val();
        var h = $("#h").val();
        if (x == 0 || y == 0 || w == 0 || h == 0) {
            alert("请裁剪图像");
        }
        var img = document.getElementById("prephoto");
        var c=document.getElementById("oldConvas");
        var ctx = c.getContext("2d");
        ctx.drawImage(img, x, y, w, h,0,0,100,100);  // 画出图片,尺寸100x100
        var newImg = c.toDataURL("image/jpeg");  // 获得图片流
        $(".photoStream").val(newImg);  // 将图片字符流存储在input中
        layer.closeAll();  // 关闭所有窗口
    }    
        <!-- 这是另一个表单,用来上传图片和其他内容 -->
        <form class="form-horizontal" role="form" method="post" onsubmit="return validate();" action="${pageContext.request.contextPath }/business/product/add.action">
            <!-- 裁剪后的图片 -->
            <div class="form-group namediv">
                <label class="col-sm-2" for="name" style="font-size: 15px;"></label>
                <div class="col-sm-6">
                    <span class="text text-danger">上传图片要求:格式jpg/jpeg/png/gif/bmp,大小&lt=2m,尺寸&lt=500x500,裁剪后图片尺寸为100x100</span>
                    <div style="width: 100px; height: 100px; border: 1px solid black;"><canvas id="oldConvas" width="100px" height="100px"></canvas></div>
                    <input type="hidden" class="photoStream" id="photoStream" name="photoStream" />
                </div>
            </div>
            <!-- 其他表单内容,不写了 -->
        </form>
    /**
     * 异步上传图片并返回图片名称
     * @param model
     * @param request
     * @param response
     * @param file 上传的图片
     * @throws Exception
     */
    @RequestMapping(value="getFileLocationAjax",method=RequestMethod.POST)
    public void getFileLocationAjax(Model model, HttpServletRequest request, HttpServletResponse response, @RequestParam("photo") CommonsMultipartFile file) throws Exception  {
        if (!file.isEmpty()) {
            InputStream in = file.getInputStream();
            String fileName = saveImage(request, in); // 调用保存图片方法
            // 保存图片名,方便剪切后删除
            model.addAttribute("fileName", fileName);
            response.setContentType("html/text; charset=UTF-8");
            PrintWriter writer = response.getWriter();
            writer.print(fileName);
        }
    }
    /**
     * 保存图片到上传路径的方法
     * @param request
     * @param in 图片输入流
     * @throws Exception
     * @return 返回文件名
     */
    public String saveImage(HttpServletRequest request, InputStream in) throws Exception {
        String fileName = UUIDUtils.getUUID() + ".jpg";  // 随机文件名
        String savePath = request.getSession().getServletContext().getRealPath("/WEB-INF/uploads") + "/"; // 获得保存路径
        File f = new File(savePath);
        if (!f.exists()) {
            f.mkdirs();
        }
        FileOutputStream fos = new FileOutputStream(savePath + fileName);
        int b = 0;
        while ((b = in.read()) != -1) {
            fos.write(b);
        }
        fos.close();
        in.close();
        return fileName;
    }   
    /**
     * 异步删除上传的文件
     * @param response
     * @param request
     * @param fileName 文件名
     * @throws Exception
     */
    @RequestMapping(value="/deleteImageAjax")
    public void deleteImageAjax(HttpServletRequest request, String fileName) throws Exception {
        System.out.println("图片名为:" + fileName);
        String savePath = request.getSession().getServletContext().getRealPath("/WEB-INF/uploads") + "/"; // 获得保存路径
        File file = new File(savePath + fileName);
        boolean flag = false;
        if (!file.exists()) {
            System.out.println("文件不存在,无法删除");
        } else {
            if (file.isFile()) {
                flag = file.delete();
            }
        }
    }
    /**
     * 根据图片流保存图片
     * @param request
     * @param data 图片流
     * @throws Exception
     * @return 图片名称
     */
    public String saveImageByStrem(HttpServletRequest request, String data) throws Exception {
        Base64 base64 = new Base64();
        // 获得图片流,实际图片数据从data:image/jpeg;base64开始
        byte[] b = base64.decodeBase64(data.substring("data:image/jpeg;base64,".length()));
        InputStream in = new ByteArrayInputStream(b);  
        String fileName = saveImage(request, in);  // 保存图片
        return fileName;
    }

心得

前端插件满天飞,经常造成选择困难症。遇到一个插件,觉得难用就放弃了,换一个插件,还是嫌麻烦,又换一个,结果进入了一个死循环。既浪费时间,又影响心情。插件是来简便开发的,不是来折腾的!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
ASP.NET MVC4中可以使用JCrop插件进行图片裁剪,并通过Ajax上传裁剪后的图片。以下是实现步骤: 1. 引入JCrop插件和jQuery库。 2. 在视图中添加一个图片标签和一个用于显示裁剪图片的标签。 ```html <div> <img src="原始图片路径" id="crop-img" /> </div> <div> <img src="" id="crop-result" /> </div> ``` 3. 在JavaScript中初始化JCrop插件。 ```javascript $(function() { $('#crop-img').Jcrop({ aspectRatio: 1, // 宽高比 onSelect: updateCoords // 选择区域后的回调函数 }); }); ``` 4. 编写回调函数updateCoords,获取裁剪后的坐标值。 ```javascript function updateCoords(c) { $('#x').val(c.x); $('#y').val(c.y); $('#w').val(c.w); $('#h').val(c.h); } ``` 5. 添加表单,包含用于保存坐标值的隐藏输入框和一个上传按钮。 ```html <form id="crop-form" method="post" enctype="multipart/form-data"> <input type="hidden" id="x" name="x" /> <input type="hidden" id="y" name="y" /> <input type="hidden" id="w" name="w" /> <input type="hidden" id="h" name="h" /> <input type="file" id="file" name="file" /> <button type="submit" id="submit">上传</button> </form> ``` 6. 绑定上传按钮点击事件,在点击上传按钮时使用Ajax上传裁剪后的图片。 ```javascript $('#submit').click(function() { var formData = new FormData($('#crop-form')[0]); $.ajax({ type: 'post', url: '上传图片的URL', data: formData, processData: false, contentType: false, success: function(data) { $('#crop-result').attr('src', '上传后的图片路径'); }, error: function() { alert('上传失败'); } }); return false; }); ``` 以上就是使用JCrop插件进行图片裁剪上传的步骤。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值