HTML5 图片本地压缩上传插件

======================前端代码=========================

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>localResizeIMG</title>
    <!--引入JQuery 用于异步上传图片-->
    <script type="text/javascript" src="dist/jquery-3.1.1.min.js"></script>
    <!--引入 lrz 插件 用于压缩图片-->
    <script type="text/javascript" src="dist/lrz.bundle.js"></script>
</head>
<body>
<input type="file" accept="image/jpeg" capture="camera">
</body>
<script>
    $("input[type=file]").change(function () {
        /* 压缩图片 */
        lrz(this.files[0], {
            width: 300 //设置压缩参数
        }).then(function (rst) {
            /* 处理成功后执行 */
            rst.formData.append('base64img', rst.base64); // 添加额外参数
            $.ajax({
                url: "upload.php",
                type: "POST",
                data: rst.formData,
                processData: false,
                contentType: false,
                success: function (data) {
                    $("<img />").attr("src", data).appendTo("body");
                }
            });
        }).catch(function (err) {
            /* 处理失败后执行 */
        }).always(function () {
            /* 必然执行 */
        })
    })
</script>
</html>
引入插件:<script type="text/javascript" src="dist/lrz.bundle.js"></script>

绑定事件:$("input[type=file]").change(function () {/* 压缩上传处理 */});

压缩图片:lrz(file, [options]);

  file 通过 input:file 得到的文件,或者直接传入图片路径

  [options] 这个参数允许忽略

    width {Number} 图片最大不超过的宽度,默认为原图宽度,高度不设定时会适应宽度

    height {Number} 图片的最大高度,默认为原图高度

    quality {Number} 图片压缩质量,取值 0 - 1,默认为 0.7

    fieldName {String} 后端接收的字段名,默认:file

返回结果:promise 对象

  then(rst) 处理成功后执行

    rst.formData 后端可处理的数据

    rst.file 压缩后的file对象,如果压缩率太低,将会是原始file对象

    rst.fileLen 生成后的图片的大小,后端可以通过此值来校验是否传输完整

    rst.base64 生成后的图片base64,后端可以处理此字符串为图片,也可以直接用于 img.src = base64

    rst.base64Len 生成后的base64的大小,后端可以通过此值来校验是否传输完整

    rst.origin 也就是原始的file对象,里面存放了一些原始文件的信息,例如大小、日期等

异步上传:processData 和 contentType 必须设为 false,否则服务端不会响应

======================后端代码=========================

<?php
$base64_image_content = $_POST['base64img'];
$output_directory = './image'; //设置图片存放路径

/* 检查并创建图片存放目录 */
if (!file_exists($output_directory)) {
    mkdir($output_directory, 0777);
}

/* 根据base64编码获取图片类型 */
if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)) {
    $image_type = $result[2]; //data:image/jpeg;base64,
    $output_file = $output_directory . '/' . md5(time()) . '.' . $image_type;
}

/* 将base64编码转换为图片编码写入文件 */
$image_binary = base64_decode(str_replace($result[1], '', $base64_image_content));
if (file_put_contents($output_file, $image_binary)) {
    echo $output_file; //写入成功输出图片路径
}
/*
 * LUploader图片压缩上传插件
 * 
 * 作者:黄磊
 * 
 * 报告漏洞,意见或建议, 请联系邮箱:xfhxbb@yeah.net
 * 
 * 创建于:2016年3月16日
 * 
 * Copyright 2016
 *
 * 获得使用本类库的许可, 您必须保留著作权声明信息。
 *
 */
(function() {
    window.LUploader = function(el, params) {
        var _self = this;
        _self.trigger=el;
        _self.params = {
            accept: 'image/*',
            multiple: false,
            maxsize: 102400,
            imgObj: {},
            showsize: false,
            quality:0.1,
            url: ''
        }
        for (var param in params) {
            _self.params[param] = params[param];
        }
        _self.init();
    };
    LUploader.prototype.init = function() {
        var _self = this;
        _self.trigger.setAttribute('accept', _self.params.accept);
        _self.params.multiple && _self.trigger.setAttribute('multiple', '');

        var btn = document.querySelector('#' + _self.trigger.getAttribute('data-LUploader'));
        btn.addEventListener('click', function() {
            _self.trigger.click();
        });
        _self.trigger.addEventListener('change', function() {
            if (!this.files.length) return;
            var files = Array.prototype.slice.call(this.files);
            files.forEach(function(file, i) {
                if (!/\/(?:jpeg|png|gif)/i.test(file.type)) return;
                var reader = new FileReader();
                _self.params.imgObj.size = file.size / 1024 > 1024 ? (~~(10 * file.size / 1024 / 1024)) / 10 + "MB" : ~~(file.size / 1024) + "KB";
                var li = document.createElement("li");
                li.innerHTML = '<div class="LUploader-progress"><span></span><input type="hidden" value="" /></div>';
                if (_self.params.showsize) {
                    var div_size = document.createElement('div');
                    div_size.className = 'LUploader-size';
                    div_size.textContent = _self.params.imgObj.size;
                    li.appendChild(div_size);
                }
                var LUploaderList = _self.trigger.parentElement.querySelector('.LUploader-list');
                if (!_self.params.multiple) { //假如是单个上传
                    if (_self.old_li) {
                        LUploaderList.removeChild(_self.old_li);
                    } else {
                        _self.old_li = li;
                    }
                }
                LUploaderList.appendChild(li);
                LUploaderList.parentElement.nextElementSibling.style['display'] = 'none';
                reader.onload = function() {
                    var params = dataSet(_self.trigger);
                    var url = _self.params.url;
                    var result = this.result;
                    var img = new Image();
                    _self.params.imgObj.src = img.src = result;
                    li.style['background-image'] = 'url(' + result + ')';
                    if (result.length <= _self.params.maxsize) {
                        img = null;
                        _self.upload(url, params, result, file.type, li);
                        return;
                    }
                    if (img.complete) {
                        callback();
                    } else {
                        img.onload = callback;
                    }

                    function callback() {
                        var data = _self.compress(img);
                        _self.upload(url, params, data, file.type, li);
                        img = null;
                    }
                };
                reader.readAsDataURL(file);
            });
        });
    };
    LUploader.prototype.compress = function(img) {
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext('2d');
        var moreCanvas = document.createElement("canvas");
        var morectx = moreCanvas.getContext("2d");
        var maxsize = 100 * 1024;
        var width = img.width;
        var height = img.height;
        var ratio;
        if ((ratio = width * height / 4000000) > 1) {
            ratio = Math.sqrt(ratio);
            width /= ratio;
            height /= ratio;
        } else {
            ratio = 1;
        }
        canvas.width = width;
        canvas.height = height;
        ctx.fillStyle = "#fff";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        var count;
        if ((count = width * height / 1000000) > 1) {
            count = ~~(Math.sqrt(count) + 1);
            var nw = ~~(width / count);
            var nh = ~~(height / count);
            moreCanvas.width = nw;
            moreCanvas.height = nh;
            for (var i = 0; i < count; i++) {
                for (var j = 0; j < count; j++) {
                    morectx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
                    ctx.drawImage(moreCanvas, i * nw, j * nh, nw, nh);
                }
            }
        } else {
            ctx.drawImage(img, 0, 0, width, height);
        }
        var ndata = canvas.toDataURL('image/jpeg', this.params.quality);
        moreCanvas.width = moreCanvas.height = canvas.width = canvas.height = 0;
        return ndata;
    };
    LUploader.prototype.upload = function(url, obj, basestr, type, li) {
        var text = window.atob(basestr.split(",")[1]);
        var buffer = new Uint8Array(text.length);
        var pecent = 0;
        for (var i = 0; i < text.length; i++) {
            buffer[i] = text.charCodeAt(i);
        }
        var span = li.querySelector('.LUploader-progress').querySelector('span');
        var hidden_input = li.querySelector('.LUploader-progress').querySelector('input');
        var xhr = new XMLHttpRequest();
        xhr.open('post', url);
        xhr.onload = function(e) {
            if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 0) {
                var data = JSON.parse(xhr.responseText);
                var result = data['status'];
                var text = result == 0 ? '上传成功' : '上传失败';
                span.style['width'] = '100%';
                span.innerHTML = text;
                hidden_input.value = data['path'];
            }
            else {
                span.innerHTML = '上传失败';
            }
        }
        xhr.upload.addEventListener('progress', function(e) {
            pecent = ~~(100 * e.loaded / e.total);
            span.style['width'] = pecent + '%';
            span.innerHTML = (pecent == 100 ? 99 : pecent) + '%';
        }, false);
        var data = {};
        for (var key in obj) {
            if (key !== 'luploader') {
                if (obj[key] == 'basestr') {
                    data[key] = basestr;
                } else {
                    data[key] = obj[key];
                }
            }
        };
        data = serializeObject(data);
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=UTF-8');
        xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
        xhr.send(data);
    }

    function isArray(arr) {
        if (Object.prototype.toString.apply(arr) === '[object Array]') return true;
        else return false;
    };

    function serializeObject(obj) {
        if (typeof obj === 'string') return obj;
        var resultArray = [];
        var separator = '&';
        for (var prop in obj) {
            if (obj.hasOwnProperty(prop)) {
                if (isArray(obj[prop])) {
                    var toPush = [];
                    for (var i = 0; i < obj[prop].length; i++) {
                        toPush.push(encodeURIComponent(prop) + '=' + encodeURIComponent(obj[prop][i]));
                    }
                    if (toPush.length > 0) resultArray.push(toPush.join(separator));
                } else {
                    resultArray.push(encodeURIComponent(prop) + '=' + encodeURIComponent(obj[prop]));
                }
            }

        }
        return resultArray.join(separator);
    };

    function dataSet(el) {
        var dataset = {};
        for (var i = 0; i < el.attributes.length; i++) {
            var attr = el.attributes[i];
            if (attr.name.indexOf('data-') >= 0) {
                dataset[toCamelCase(attr.name.split('data-')[1])] = attr.value;
            }
        }
        return dataset;
    }

    function toCamelCase(string) {
        return string.toLowerCase().replace(/-(.)/g, function(match, group1) {
            return group1.toUpperCase();
        });
    };
})();


<!doctype html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="Access-Control-Allow-Origin" content="*">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui">
    <meta content="yes" name="apple-mobile-web-app-capable">
    <meta content="black" name="apple-mobile-web-app-status-bar-style">
    <meta content="telephone=no" name="format-detection">
    <meta content="email=no" name="format-detection">
    <title>移动端图片压缩上传</title>
    <link rel="stylesheet" href="css/LUploader.css">
    <style>
    * {
        margin: 0;
        padding: 0;
    }
    h1{
    background-color: #19b5ee;
    color: #fff;
    font-size: 25px;
    text-align: center;
    padding: 10px;
    }
    li {
        list-style-type: none;
    }
    input {
        outline: none;
        -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
    }
    </style>
</head>

<body>
    <h1>LUploader移动端图片压缩上传</h1>
    <div class="LUploader" id="demo1">
        <div class="LUploader-container">
            <input data-LUploader='demo1' data-form-file='basestr' data-upload-type='front' type="file" />
            <ul class="LUploader-list"></ul>
        </div>
        <div>
            <div class="icon icon-camera font20"></div>
            <p>单击上传</p>
        </div>
    </div>
    <script src="js/LUploader.js?r=<?php echo  time();?>"></script>
    <script>
    [].slice.call(document.querySelectorAll('input[data-LUploader]')).forEach(function(el) {
        new LUploader(el, {
            url: './upload.php',//post请求地址
            multiple: false,//是否一次上传多个文件 默认false
            maxsize: 102400,//忽略压缩操作的文件体积上限 默认100kb
            accept: 'image/*',//可上传的图片类型
            quality: 0.5,//压缩比 默认0.1  范围0.1-1.0 越小压缩率越大
            showsize:true//是否显示原始文件大小 默认false
        });
    });
    </script>
</body>

</html>

 

 

posted @ 2018-08-08 15:24  6671  阅读(643)  评论(0编辑  收藏  举报