• 演示webuploader和cropperjs图片裁剪上传


    最近有个项目要在浏览器端裁剪并上传图片。由于缺乏人力,只能我上阵杀敌。通过参考各种文章,最后决定用cropperjs进行图片裁剪,用webuploader上传文件。本文涉及到的知识至少有Java基础、SpringMVC、thymeleaf模版引擎、JS基础、JQuery基础、Bootstrap组件,但是文章重点只是cropperjs和webuploader的组合运用,其他的都是辅助。

    1. 依赖JS库

    webuploader官网
    cropperjs演示主页
    cropperjs开源主页

    2. 核心流程

    • 2.1 选择文件按钮

    previewImg用于预览上传后的图片;picker用于选择图片,webuploader会自动给picker赋予选择文件的特性。fileInput用于接收文件数据。

    <div class="form-group"> 
       <img id="previewImg" width="200px" /> 
       <div> 
        <a href="javascript:void(0)" id="picker">选择图片</a> 
        <input type="file" id="fileInput" style="display: none" /> 
       </div> 
      </div>
    

    下面代码给fileInput组件触发了点击事件

        $("#picker").on('click', function () {
            $("#fileInput").trigger("click");
        });
    
    • 2.2 定义组件参数和事件

    以下代码定义上传组件对象

        var uploader = WebUploader.create({
            auto: true,// 选完文件后,是否自动上传。
            server: '/upload',
            fileSingleSizeLimit: 2 * 1024 * 1024,
            duplicate: true,
            accept: {// 只允许选择图片文件。
                title: 'Images',
                extensions: 'jpg,jpeg,png',
                mimeTypes: 'image/jpg,image/jpeg,image/png'
            },
            //如果有表单数据要上传,可以给formData赋值
            formData: {
                id: 0
            }
        });
    

    以下代码定义上传组件事件。WebUploader组件不提供UI,如果需要定制界面,实现下面的方法即可。

        //提交额外的表单数据
        uploader.on('uploadBeforeSend', function (object, data, header) {
            data.id = $('#id').val();
        });
    
        // 当有文件被添加进队列的时候
        uploader.on('fileQueued', function (file) {
            $('#file_list').append('<div id="' + file.id + '" class="item">' +
                '<h4 class="info">' + file.name + '</h4>' +
                '<p class="state">等待上传...</p>' +
                '</div>');
        });
    
        // 上传成功
        uploader.on('uploadSuccess', function (file, response) {
            $('#' + file.id).find('p.state').text('已上传');
            console.log(response._raw);
            var object = $.parseJSON(response._raw);
            //给预览组件赋值
            $('#previewImg').attr("src", object.url);
        });
    
        // 上传发生错误
        uploader.on('uploadError', function (file) {
            $('#' + file.id).find('p.state').text('上传出错');
        });
    
        // 上传中
        uploader.on('startUpload', function (file, rs) {
            console.log("文件正在上传中,请稍候");
        });
    
    • 2.3 定义裁剪组件参数和事件

    以下代码定义裁剪图片的对话框,cropperImage是上传后的图片,被裁剪的目标对象。

    <div class="modal" id="cropperImageModal" tabindex="-1" role="dialog" aria-labelledby="cropperImageModal"
         aria-hidden="true">
        <div class="modal-dialog" style=" 50%;">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
                    <h4 class="modal-title">裁剪图片</h4>
                </div>
                <div class="modal-body">
                    <!-- cropperImage是上传后的图片,被裁剪的目标对象 -->
                    <img src="" id="cropperImage" style="max- 100%"/>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal" id="modalClose">关闭</button>
                    <button type="button" class="btn btn-primary" id="modalSubmit">保存</button>
                </div>
            </div>
        </div>
    </div>
    

    以下代码定义图片裁剪参数,更多参数参考cropper.js的API详解。如果不需要固定裁剪区域大小,删除ready函数即可。

        var cropperImage = $("#cropperImage");
        var cropperOptions = {
            viewMode: 1,
            dragMode: 'none',
            aspectRatio: 1,
            background: false,
            autoCropArea: 0.6,
            crop: function (event) {
                //裁剪的实时事件
                console.log(event.detail.width);
                console.log(event.detail.height);
            },
            ready: function () {
                //限定裁剪区域大小为500
                cropperImage.cropper('crop');
                cropperImage.cropper('setData', {
                     500,
                    height: 500
                })
            }
        };
    
    • 2.5 触发裁剪和上传事件

    fileInput组件的change事件会采用FileReader对象获得上传的Image,初始化cropperjs裁剪方法。

        $("#fileInput").on('change', function () {
            var file = this.files[0];
            //定义读文件对象
            var reader = new FileReader();
            reader.onload = function () {
                imageOnload(reader.result);
    
            };
            reader.readAsDataURL(file);//File对象转换为dataURL
        });
    
        //图片对象加载方法
        function imageOnload(url) {
            var cropperImg = new Image();
            cropperImg.src = url;
            //destroy方法是为了重入不出错
            cropperImage.cropper('destroy').attr('src', url).cropper(cropperOptions);
            cropperImg.onload = function () {
                //弹窗裁剪
                $('#cropperImageModal').modal();
                $("#modalClose").on('click', function () {
                    $("#fileInput").val('');
                    $('#cropperImageModal').modal('hide');
                });
    
                $("#modalSubmit").on('click', function () {
                    var canVas = $("#cropperImage").cropper("getCroppedCanvas", {});//获取裁剪后得到的canvas数据
                    var file = convertBase64UrlToBlob(canVas.toDataURL('image/jpeg', '0.0'));//将canvas转换为Blob格式
                    uploader.addFiles(file);//将裁剪后的图片添加进webuploader上传到后台
                    $('#cropperImageModal').modal('hide');
                    $("#fileInput").val('');
                });
            };
        }
    

    采用cropperImage.cropper('getCroppedCanvas').toblob(function(blob){})也可以获取图片二进制对象,但是默认是png格式,体积很大,不利于网络传输,采用下面的方法可以指定图片格式。

        /**
         * base64转为blob,图片为jpeg格式
         */
        function convertBase64UrlToBlob(urlData) {
            //去掉url的头,并转换为byte
            var bytes = window.atob(urlData.split(',')[1]);
            //处理异常,将ascii码小于0的转换为大于0
            var ab = new ArrayBuffer(bytes.length);
            var ia = new Uint8Array(ab);
            for (var i = 0; i < bytes.length; i++) {
                ia[i] = bytes.charCodeAt(i);
            }
            return new Blob([ab], {type: 'image/jpeg'});
        }
    
    • 2.6 后端接口实现
    
    @Controller
    public class IndexController {
    
        protected final Logger logger = LoggerFactory.getLogger(getClass());
    
        @RequestMapping("/index")
        public String list(ModelMap map) {
            return "index";
        }
    
        @PostMapping("/upload")
        @ResponseBody
        public UploadFileVo uploadFile(@RequestParam("file") MultipartFile file, @RequestParam("id") Integer id, HttpServletResponse response) {
            response.setContentType("text/html");
            //保存图片到服务端,返回访问地址
            UploadFileVo uploadFileVo = new UploadFileVo();
            //这里为了演示,返回一张网图
            uploadFileVo.setUrl("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png");
            logger.info("上传成功,url:{},id:{}", uploadFileVo.getUrl(), id);
            return uploadFileVo;
        }
    
    }
    
    • 2.7 最终效果图
      webuploader和croopper图片裁剪上传

    3. 完整代码

    查阅演示代码

    参考

    https://www.codingbrick.com/archives/456.html

  • 相关阅读:
    Python Day 72 Django框架 图书管理系统回顾ORM 正向查询、反向查询、跨表查询、Django终端打印SQL语句、ORM十三个必会操作总结
    Python Day 71 Django框架setting源码分析、基于该源码原理实现用户在暴露的setting文件中自定义的配置就使用用户配置的,没配置就是用全局默认的
    Python Day 70 利用Django框架做的一个bbs小项目
    Python Day 69 Django框架、Forms组件、forms组件的钩子函数、form组件前端处理逻辑三种方式、form常用字段及插件、Form所有内置字段、字段校验两种方式
    Python Day 68 Django框架、CBV源码简单理解
    Python Day 67 Dango框架图解(总结)、Wsgiref和uwsgi、前后端传输数据的编码格式、From表单和Ajax方式在前端往后端发送文件、补充一下页面清缓存
    python 学习分享-实战篇简单的ftp
    python 学习分享-面向对象2
    python 学习分享-实战篇选课系统
    python 学习分享-面向对象
  • 原文地址:https://www.cnblogs.com/xiaoyangjia/p/15677347.html
Copyright © 2020-2023  润新知