H5实现图片预览、裁剪、批量上传

前端代码: 

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="A basic demo of Cropper.">
  <meta name="keywords" content="HTML, CSS, JS, JavaScript, jQuery plugin, image cropping, image crop, image move, image zoom, image rotate, image scale, front-end, frontend, web development">
  <meta name="author" content="Fengyuan Chen">
  <title>Cropper Test</title>
  <link rel="stylesheet" href="../dist/cropper.css">
  <style>
  .upload-img {
      width: 35%;
      overflow: hidden;
      margin-right: 20px;
  }
  .upload-preview,.upload-opr {
      overflow: hidden;
  }
  .upload-preview {
      margin-top: 50px;
  }
  .img-preview {
      float: left;
      overflow: hidden;
      border: 1px solid #7E7E7E;
      margin-right: 10px;
  }
  </style>
</head>
<body>
    <div class="upload-opr">
    <button id="upload-btn" type="button" style="display: none;">上传图片</button>
    <button id="enable-cropper" type="button" style="display: none;">重新裁剪</button>
    <input type="file" id="select-image" accept="image/*" />
    </div>
    <div class="upload-img">
    <img src="https://img-blog.csdnimg.cn/2022010707204559759.jpeg"/>
    </div>
    <div class="upload-preview">
    <div class="img-preview" style="width: 400px;height: 300px;"></div>
    <div class="img-preview" style="width: 240px;height: 180px;"></div>
    <div class="img-preview"  style="width: 120px;height: 90px;"></div>
    </div>
    <!-- Scripts -->
    <script src="../assets/js/jquery.min.js"></script>
    <script src="../dist/cropper.js"></script>
    <script src="../assets/js/async.js"></script>
    <script>
        $(function(){
            var $image = $('.upload-img img');
            $image.cropper({
                preview: '.img-preview', //不同尺寸预览区
                aspectRatio: 4/3, //裁剪比例,NaN-自由选择区域
                autoCropArea: 0.9, //初始裁剪区域占图片比例
                crop: function(data) { //裁剪操作回调
                }
            });
            var fileName; //选择上传的文件名
            $('#select-image').change(function(){
                var file = this.files[0];
                fileName = file.name;
                var reader = new FileReader();
                //reader回调,重新初始裁剪区
                reader.onload = function(){
                    // 通过 reader.result 来访问生成的 DataURL
                    var url = reader.result;
                    //选择图片后重新初始裁剪区
                    $('.upload-img img').attr('src', url);
                    $image.cropper('reset', true).cropper('replace', url);
                    //显示上传按钮
                    $('#upload-btn').show();
                    //隐藏重新裁剪按钮
                    $('#enable-cropper').hide();
                };
                reader.readAsDataURL(file);
            });

            /*解除裁剪区锁定*/
            $('#enable-cropper').click(function() {
                $image.cropper('enable');
                $('#upload-btn').show();
                $(this).hide();
            });

            /*
             * 上传图片
             */
            $('#upload-btn').click(function() {
                var type = $image.attr('src').split(';')[0].split(':')[1];
                //series 中的方法顺序执行裁剪不同尺寸的图片得到blob后调用callback上传图片
                async.series({
                    '_': function(callback) {
                        $image.cropper("getCroppedCanvas").toBlob(function(blob) {
                            callback(null, blob);
                        }, type);
                    },
                    '400x300': function(callback) {
                        $image.cropper("getCroppedCanvas", { "width": 400, "height": 300 }).toBlob(function(blob) {
                            callback(null, blob);
                        }, type);
                    },
                    '240x180': function(callback) {
                        $image.cropper("getCroppedCanvas", { "width": 240, "height": 180 }).toBlob(function(blob) {
                            callback(null, blob);
                        }, type);
                    },
                    '120x90': function(callback) {
                        $image.cropper("getCroppedCanvas", { "width": 120, "height": 90 }).toBlob(function(blob) {
                            callback(null, blob);
                        }, type);
                    }
                },
                //异步最终回调,上传图片
                function(err, results){
                    //results: {'_', blob Object, '400x300': blob Object, '240x180': blob Object, ...}
                    console.log("results", JSON.stringify(results));
                    var formData = new FormData();
                    for(var key in results) {
                        var wh = key.split('x',2);
                        var sizeName = fileName;
                        if(wh.length == 2) {
                            var idx = fileName.lastIndexOf('.')
                            sizeName = fileName.substring(0, idx)+'_' + key + fileName.substring(idx)
                        }
                        //把要上传的图片blob加到formData中
                        formData.append("file", results[key], sizeName);
                    }
                    $.ajax({
                        type: "POST",
                        url: '/multiUpload',
                        data: formData,
                        contentType: false, //必须
                        processData: false, //必须
                        dataType: "json",
                        success: function(retJson){
                            //上传成功回调函数
                            if(uploadCallback && typeof uploadCallback == 'function') {
                                uploadCallback(retJson);
                            } else {
                                console.log(JSON.stringify(retJson));
                            }
                            if(retJson.code == 0) {
                                $('#upload-btn').hide();
                                $image.cropper("disable");
                                $('#enable-cropper').show();
                            }
                        },
                        error : function() {
                            $('#upload-btn').hide();
                            $image.cropper("disable");
                            $('#enable-cropper').show();
                            console.log('failed');
                            alert('上传失败');
                        },
                        beforeSend: function(){
                        },
                        complete: function(){

                        }
                    });
                });
            });
        })
    </script>
</body>
</html>

服务端代码:结合Spring MVC实现上传,关于spring mvc上传网上很多,配置就不详细说明了

@RestController
public class MainController {
    private static SimpleDateFormat df = new SimpleDateFormat("YYYY/MM/dd/");

    private String uploadUrlPrefix = "http://localhost/upload";
    private String uploadDir = "/data/upload";
    
    @RequestMapping(value = "/multiUpload", name = "批量上传图片")
    public String uploadMulti(@RequestParam("file") CommonsMultipartFile[] files) throws IOException {
        JSONObject json = new JSONObject();
        if(files == null) {
            json.put("code", -1);
            json.put("message", "没有上传文件");
            return json.toJSONString();
        }
        JSONArray jsonArray = new JSONArray();
        json.put("data", jsonArray);
        String uuid = UUID.randomUUID().toString();
        for(CommonsMultipartFile file : files) {
            String oriFileName = file.getOriginalFilename();
            StringBuilder newFileName = new StringBuilder();
            boolean isBase = false;
            if(oriFileName.matches(".*_\\d+x\\d+\\.\\w+")) {
                newFileName.append(oriFileName.replaceFirst("(.*)(_\\d+x\\d+\\.\\w+)", uuid+"$2"));
            } else {
                newFileName.append(uuid).append(oriFileName.substring(oriFileName.lastIndexOf('.')));
                isBase = true;
            }
            String timeDir = df.format(new Date());
            String imgPath = uploadDir + File.separatorChar + timeDir + fileName;
            log.info("save file name: {}", newFileName);
            
            File imgFile = new File(imgPath);
            if(!imgFile.getParentFile().exists()) {
                imgFile.getParentFile().mkdirs();
            }
            //保存文件
            file.transferTo(imgFile);
            JSONObject imgJson = new JSONObject();
            imgJson.put("oriFileName", oriFileName);
            imgJson.put("state", "SUCCESS");
            imgJson.put("url", uploadUrlPrefix + "/" + uri);
            jsonArray.add(imgJson);
            if(isBase) {
                json.put("baseUrl", imgJson.getString("url"));
            }
        }
        json.put("code", 0);
        json.put("message", "上传成功");
        return json.toJSONString();
    }
}

cropper js 参考:https://fengyuanchen.github.io/cropper/

async异步库参考:https://github.com/caolan/async

大体思路:

  1.  用cropper js 实现图片预览,裁剪
  2.  调用cropper js的getCroppedCanvas来获取不同尺寸的图片canvas
  3.  结合async 实现顺序地从canvas.toBlob的回调中获取到blob,很好的解决了异步的问题,这点非常重要
  4. 用FormData装载图片,ajax上传

效果:

105732_x4P7_565351.png

 

 

 

转载于:https://my.oschina.net/u/565351/blog/692777

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值