html5上传前压缩图片尺寸、质量

图片上传功能是个比较常用的功能。现代手机图片像素较大,一张图片都有好几M,在服务器带宽较小的情况下(本人苦逼小站只有1Mbps)对用户的耐心是个很大的挑战,此时在浏览器端压缩再上传就很有必要了。

[一]环境:jdk8+tomcat8

[二]框架:springmvc

[三]代码:

maven:核心包,其他的我就不贴了

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

html,引入了bootstrap和jquery,不贴了

<input type="file" accept="image/*" value="${pageContext.request.contextPath}/upload" multiple style="display: none"/>
<button id="upload" class="btn btn-success btn-md">上传图片</button>
预览:<div></div><hr>
<div class="progress"><span></span></div>
<canvas id="canvans" style="max-width: 400px;">

</canvas>

javascript

<script>
        //初始化
        var maxFileSize=150*1024;
        var canvas = document.getElementById("canvans");
        var ctx = canvas.getContext("2d");
        //
        //        var fileChoose = $("input");
        //触发隐藏的上传按钮
        $("#upload").on("click",function () {
            $("input[type='file']").click();
        }).on("touchstart",function () {
            $(this).addClass("touch");
        }).on("touchend",function () {
            $(this).removeClass("touch");
        });
        //
        $("input").on("change",chg);
        function chg() {
            if(!this.files.length){
                return;
            }
            var files = Array.prototype.slice.call(this.files);
            console.info("files==="+files);
            if(files.length>3){
                alert("最多只能上传3张图片");
                return;
            }
            files.forEach(function (file, i) {
                if(!/jpeg|jpg|png/.test(file.type)){
                    alert("仅支持上传jpgjpegpng格式的图片");
                    return;
                }
                var fileReader = new FileReader();
                //获取图片大小
                var fileSize = file.size/1024>1024?(file.size/1024/1024).toFixed(2)+"MB":~~(file.size/1024)+"KB";
                $(".progress").text(fileSize);
                //FILE API读取文件
                fileReader.onload=function () {
                    var result = this.result;
                    var image = new Image();
                    image.src=result;
                    //超出大小,压缩
                    if(result.length>maxFileSize){
                        if(image.complete){
                            callback();
                        }else{
                            image.onload = callback;
                            compress(image);
                        }
                    }else{
                        image = null;
                        upload(result,file.type);
                        return;
                    }
                    function callback(){
                        var data = compress(image);
                        upload(data,file.type);
                    }
                }
                fileReader.readAsDataURL(file);
            });
            //canvas对图片压缩
            function compress(image){
                var initImgSize = image.src.length;
                var width = image.width;
                var height = image.height;
                console.info(initImgSize+"/"+width+"/"+height);
                //如果图片大于200Kb,将图片压缩至200Kb以下
                var ration;//压缩比
                if(width*height>2000000){
                    ration = Math.sqrt(width*height/2000000);
                    width/=ration;
                    height/=ration;
                }else{
                    ration = 1;
                }
                canvas.width = width;
                canvas.height = height;
                //        铺底色
//                ctx.fillStyle = "#fff";
//                ctx.fillRect(0, 0, canvas.width, canvas.height);
                //图片过大需要进行瓦片绘制,暂不做处理
                ctx.drawImage(image,0,0,canvas.width,canvas.height);
                //进行压缩
                var newdata = canvas.toDataURL("image/jpeg",0.3);
                console.info("before"+initImgSize);
                console.info("after"+newdata.length);
                console.info("rate"+(100*(initImgSize-newdata.length)/initImgSize)+"%");
                return newdata;
            }

        }

        //    图片上传,将base64的图片转成二进制对象,塞进formdata上传
        function upload(basestr,type){
            var text = window.atob(basestr.split(",")[1]);
            var buffer = new Uint8Array(text.length);
            var pecent = 0, loop = null;
            for (var i = 0; i < text.length; i++) {
                buffer[i] = text.charCodeAt(i);
            }
            var blob = getBlob([buffer], type);
            var xhr = new XMLHttpRequest();
            var formdata = getFormData();
            console.info(blob);
            formdata.append('data', blob);
//            formdata.append("filename","abc.jpg");
            xhr.open('post', 'http://localhost:8090/upload/');
            xhr.onreadystatechange = function() {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    var jsonData = JSON.parse(xhr.responseText);
                    var text = jsonData.path ? '上传成功' : '上传失败';
                    console.log(text + '' + jsonData.path);
                    $("#abc").attr("src","http://localhost:8090/"+jsonData.path);
                    clearInterval(loop);
                    //当收到该消息时上传完毕
                    $(".progress span").animate({'width': "100%"}, pecent < 95 ? 200 : 0, function() {
                        $(this).html(text);
                    });
//                    if (!imagedata.path) return;
//                    alert("imagePath="+imagedata.path);
//                        $(".pic-list").append('<a href="' + imagedata.path + '">' + imagedata.name + '' + imagedata.size + '<img src="' + imagedata.path + '" /></a>');
                }
            };
            //数据发送进度,前50%展示该进度
            xhr.upload.addEventListener('progress', function(e) {
                if (loop) return;
                pecent = ~~(100 * e.loaded / e.total);
//                    $li.find(".progress span").css('width', pecent + "%");
                $(".progress span").text(pecent+"%");
//                console.info("progress"+pecent);
//                if (pecent == 50) {
//                    mockProgress();
//                }
            }, false);
            //数据后50%用模拟进度
            function mockProgress() {
                if (loop) return;
                loop = setInterval(function() {
                    pecent++;
                    console.info(pecent);
                    if (pecent == 99) {
                        clearInterval(loop);
                    }
                }, 100)
            }
            xhr.send(formdata);
        }

        /**
         * 获取blob对象的兼容性写法
         * @param buffer
         * @param format
         * @returns {*}
         */
        function getBlob(buffer, format) {
            try {
                return new Blob(buffer, {type: format});
            } catch (e) {
                var bb = new (window.BlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder);
                buffer.forEach(function(buf) {
                    bb.append(buf);
                });
                return bb.getBlob(format);
            }
        }
        /**
         * 获取formdata
         */
        function getFormData() {
            var isNeedShim = ~navigator.userAgent.indexOf('Android')
                    && ~navigator.vendor.indexOf('Google')
                    && !~navigator.userAgent.indexOf('Chrome')
                    && navigator.userAgent.match(/AppleWebKit\/(\d+)/).pop() <= 534;
            return isNeedShim ? new FormDataShim() : new FormData()
        }
    </script>

java

/**
 * 上传前压缩
 *
 * @return
 */
@ResponseBody
@RequestMapping("/upload")
public Map<String, Object> upload(HttpServletRequest request, @RequestParam("data") MultipartFile file, String filename) throws IOException {
    Map<String, Object> result = new HashMap<String, Object>();
    
    //基本属性打印
    System.out.print("OriginalFilename="+file.getOriginalFilename()+"\n ContentType="+file.getContentType()+"\n Name="+file.getName()+"\n Bytes="+file.getBytes()+"\n Size="+file.getSize());
    String n_dp = new SimpleDateFormat("yyyyMMdd").format(new Date());
    String uploadDir = request.getSession().getServletContext().getRealPath("/attached/image/" + n_dp+"/");
    File f = new File(uploadDir);
    if (!f.exists()) {
        if (f.mkdirs()) {
            System.out.println("创建文件夹成功!" + uploadDir);
        } else {
            System.out.println("创建文件失败");
        }
    }

    String n_fn = new SimpleDateFormat("HHmmss").format(new Date()) + "_" + randomString() + ".jpg";
    File targetFile = new File(uploadDir, n_fn);
    file.transferTo(targetFile);
    result.put("path", "/attached/image/" + n_dp+"/"+ n_fn);
    return result;
}


private String randomString() {
    long t = System.nanoTime();
    String str = String.valueOf(t);
    return str.substring(str.length() - 7);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值