html5——多图上传
html5 2017-01-18 09:20:39

 

PHP Code复制内容到剪贴板
  1. <!DOCTYPE html>  
  2. <html lang="en">  
  3. <head>  
  4.     <meta charset="UTF-8">  
  5.     <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">  
  6.     <title>移动端图片压缩上传demo</title>  
  7.     <style>  
  8.         *{margin: 0;padding: 0;}  
  9.         li{list-style-type: none;}  
  10.         a,input{outline: none;-webkit-tap-highlight-color:rgba(0,0,0,0);}  
  11.         #choose{display: none;}  
  12.         canvas{width: 100%;border: 1px solid #000000;}  
  13.         #upload{display: block;margin: 10px;height: 60px;text-align: center;line-height: 60px;border: 1px solid;border-radius: 5px;cursor: pointer;}  
  14.         .touch{background-color: #ddd;}  
  15.         .img-list{margin: 10px 5px;}  
  16.         .img-list li{position: relative;display: inline-block;width: 100px;height: 100px;margin: 5px 5px 20px 5px;border: 1px solid rgb(100,149,198);background: #fff no-repeat center;background-size: cover;}  
  17.         .progress{position: absolute;width: 100%;height: 20px;line-height: 20px;bottom: 0;left: 0;background-color:rgba(100,149,198,.5);}  
  18.         .progress span{display: block;width: 0;height: 100%;background-color:rgb(100,149,198);text-align: center;color: #FFF;font-size: 13px;}  
  19.         .size{position: absolute;width: 100%;height: 15px;line-height: 15px;bottom: -18px;text-align: center;font-size: 13px;color: #666;}  
  20.         .tips{display: block;text-align:center;font-size: 13px;margin: 10px;color: #999;}  
  21.         .pic-list{margin: 10px;line-height: 18px;font-size: 13px;}  
  22.         .pic-list a{display: block;margin: 10px 0;}  
  23.         .pic-list a img{vertical-align: middle;max-width: 30px;max-height: 30px;margin: -4px 0 0 10px;}  
  24.     </style>  
  25. </head>  
  26. <body>  
  27. <input type="file" id="choose" accept="image/*" multiple>  
  28. <ul class="img-list"></ul>  
  29. <a id="upload">上传图片</a>  
  30. <span class="tips">只允许上传jpg、png及gif</span>  
  31. <div class="pic-list">  
  32.     你上传的图片(图片有效期为1分钟):  
  33. </div>  
  34.   
  35. <script type="text/javascript" src="../requireCommon/js/jquery.min.js"></script>  
  36. <script>  
  37.     var filechooser = document.getElementById("choose");  
  38.     //    用于压缩图片的canvas  
  39.     var canvas = document.createElement("canvas");  
  40.     var ctx = canvas.getContext('2d');  
  41.     //    瓦片canvas  
  42.     var tCanvas = document.createElement("canvas");  
  43.     var tctx = tCanvas.getContext("2d");  
  44.     var maxsize = 100 * 1024;  
  45.     $("#upload").on("click"function() {  
  46.                 filechooser.click();  
  47.             })  
  48.             .on("touchstart"function() {  
  49.                 $(this).addClass("touch")  
  50.             })  
  51.             .on("touchend"function() {  
  52.                 $(this).removeClass("touch")  
  53.             });  
  54.     filechooser.onchange = function() {  
  55.         if (!this.files.length) return;  
  56.         var files = Array.prototype.slice.call(this.files);  
  57.         if (files.length > 9) {  
  58.             alert("最多同时只可上传9张图片");  
  59.             return;  
  60.         }  
  61.         files.forEach(function(file, i) {  
  62.             if (!/\/(?:jpeg|png|gif)/i.test(file.type)) return;  
  63.             var reader = new FileReader();  
  64.             var li = document.createElement("li");  
  65. //          获取图片大小  
  66.             var size = file.size / 1024 > 1024 ? (~~(10 * file.size / 1024 / 1024)) / 10 + "MB" : ~~(file.size / 1024) + "KB";  
  67.             li.innerHTML = '<div class="progress"><span></span></div><div class="size">' + size + '</div>';  
  68.             $(".img-list").append($(li));  
  69.             reader.onload = function() {  
  70.                 var result = this.result;  
  71.                 var img = new Image();  
  72.                 img.src = result;  
  73.                 $(li).css("background-image""url(" + result + ")");  
  74.                 //如果图片大小小于100kb,则直接上传  
  75.                 if (result.length <= maxsize) {  
  76.                     img = null;  
  77.                     upload(result, file.type, $(li));  
  78.                     return;  
  79.                 }  
  80. //      图片加载完毕之后进行压缩,然后上传  
  81.                 if (img.complete) {  
  82.                     callback();  
  83.                 } else {  
  84.                     img.onload = callback;  
  85.                 }  
  86.                 function callback() {  
  87.                     var data = compress(img);  
  88.                     upload(data, file.type, $(li));  
  89.                     img = null;  
  90.                 }  
  91.             };  
  92.             reader.readAsDataURL(file);  
  93.         })  
  94.     };  
  95.     //    使用canvas对大图片进行压缩  
  96.     function compress(img) {  
  97.         var initSize = img.src.length;  
  98.         var width = img.width;  
  99.         var height = img.height;  
  100.         //如果图片大于四百万像素,计算压缩比并将大小压至400万以下  
  101.         var ratio;  
  102.         if ((ratio = width * height / 4000000) > 1) {  
  103.             ratio = Math.sqrt(ratio);  
  104.             width /= ratio;  
  105.             height /= ratio;  
  106.         } else {  
  107.             ratio = 1;  
  108.         }  
  109.         canvas.width = width;  
  110.         canvas.height = height;  
  111. //        铺底色  
  112.         ctx.fillStyle = "#fff";  
  113.         ctx.fillRect(0, 0, canvas.width, canvas.height);  
  114.         //如果图片像素大于100万则使用瓦片绘制  
  115.         var count;  
  116.         if ((count = width * height / 1000000) > 1) {  
  117.             count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片  
  118. //            计算每块瓦片的宽和高  
  119.             var nw = ~~(width / count);  
  120.             var nh = ~~(height / count);  
  121.             tCanvas.width = nw;  
  122.             tCanvas.height = nh;  
  123.             for (var i = 0; i < count; i++) {  
  124.                 for (var j = 0; j < count; j++) {  
  125.                     tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);  
  126.                     ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);  
  127.                 }  
  128.             }  
  129.         } else {  
  130.             ctx.drawImage(img, 0, 0, width, height);  
  131.         }  
  132.         //进行最小压缩  
  133.         var ndata = canvas.toDataURL('image/jpeg', 0.1);  
  134.         console.log('压缩前:' + initSize);  
  135.         console.log('压缩后:' + ndata.length);  
  136.         console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%");  
  137.         tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;  
  138.         return ndata;  
  139.     }  
  140.     //    图片上传,将base64的图片转成二进制对象,塞进formdata上传  
  141.     function upload(basestr, type, $li) {  
  142.         var text = window.atob(basestr.split(",")[1]);  
  143.         var buffer = new Uint8Array(text.length);  
  144.         var pecent = 0, loop = null;  
  145.         for (var i = 0; i < text.length; i++) {  
  146.             buffer[i] = text.charCodeAt(i);  
  147.         }  
  148.         var blob = getBlob([buffer], type);  
  149.         var xhr = new XMLHttpRequest();  
  150.         var formdata = getFormData();  
  151.         formdata.append('imagefile', blob);  
  152.         xhr.open('post''/cupload');  
  153.         xhr.onreadystatechange = function() {  
  154.             if (xhr.readyState == 4 && xhr.status == 200) {  
  155.                 var jsonData = JSON.parse(xhr.responseText);  
  156.                 var imagedata = jsonData[0] || {};  
  157.                 var text = imagedata.path ? '上传成功' : '上传失败';  
  158.                 console.log(text + ':' + imagedata.path);  
  159.                 clearInterval(loop);  
  160.                 //当收到该消息时上传完毕  
  161.                 $li.find(".progress span").animate({'width'"100%"}, pecent < 95 ? 200 : 0, function() {  
  162.                     $(this).html(text);  
  163.                 });  
  164.                 if (!imagedata.path) return;  
  165.                 $(".pic-list").append('<a href="' + imagedata.path + '">' + imagedata.name + '(' + imagedata.size + ')<img src="' + imagedata.path + '" /></a>');  
  166.             }  
  167.         };  
  168.         //数据发送进度,前50%展示该进度  
  169.         xhr.upload.addEventListener('progress'function(e) {  
  170.             if (loop) return;  
  171.             pecent = ~~(100 * e.loaded / e.total) / 2;  
  172.             $li.find(".progress span").css('width', pecent + "%");  
  173.             if (pecent == 50) {  
  174.                 mockProgress();  
  175.             }  
  176.         }, false);  
  177.         //数据后50%用模拟进度  
  178.         function mockProgress() {  
  179.             if (loop) return;  
  180.             loop = setInterval(function() {  
  181.                 pecent++;  
  182.                 $li.find(".progress span").css('width', pecent + "%");  
  183.                 if (pecent == 99) {  
  184.                     clearInterval(loop);  
  185.                 }  
  186.             }, 100)  
  187.         }  
  188.         xhr.send(formdata);  
  189.     }  
  190.     /**  
  191.      * 获取blob对象的兼容性写法  
  192.      * @param buffer  
  193.      * @param format  
  194.      * @returns {*}  
  195.      */  
  196.     function getBlob(buffer, format) {  
  197.         try {  
  198.             return new Blob(buffer, {type: format});  
  199.         } catch (e) {  
  200.             var bb = new (window.BlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder);  
  201.             buffer.forEach(function(buf) {  
  202.                 bb.append(buf);  
  203.             });  
  204.             return bb.getBlob(format);  
  205.         }  
  206.     }  
  207.     /** 
  208.      * 获取formdata 
  209.      */  
  210.     function getFormData() {  
  211.         var isNeedShim = ~navigator.userAgent.indexOf('Android')  
  212.                 && ~navigator.vendor.indexOf('Google')  
  213.                 && !~navigator.userAgent.indexOf('Chrome')  
  214.                 && navigator.userAgent.match(/AppleWebKit\/(\d+)/).pop() <= 534;  
  215.         return isNeedShim ? new FormDataShim() : new FormData()  
  216.     }  
  217.     /** 
  218.      * formdata 补丁, 给不支持formdata上传blob的android机打补丁 
  219.      * @constructor 
  220.      */  
  221.     function FormDataShim() {  
  222.         console.warn('using formdata shim');  
  223.         var o = this,  
  224.                 parts = [],  
  225.                 boundary = Array(21).join('-') + (+new Date() * (1e16 * Math.random())).toString(36),  
  226.                 oldSend = XMLHttpRequest.prototype.send;  
  227.         this.append = function(name, value, filename) {  
  228.             parts.push('--' + boundary + '\r\nContent-Disposition: form-data; name="' + name + '"');  
  229.             if (value instanceof Blob) {  
  230.                 parts.push('; filename="' + (filename || 'blob') + '"\r\nContent-Type: ' + value.type + '\r\n\r\n');  
  231.                 parts.push(value);  
  232.             }  
  233.             else {  
  234.                 parts.push('\r\n\r\n' + value);  
  235.             }  
  236.             parts.push('\r\n');  
  237.         };  
  238.         // Override XHR send()  
  239.         XMLHttpRequest.prototype.send = function(val) {  
  240.             var fr,  
  241.                     data,  
  242.                     oXHR = this;  
  243.             if (val === o) {  
  244.                 // Append the final boundary string  
  245.                 parts.push('--' + boundary + '--\r\n');  
  246.                 // Create the blob  
  247.                 data = getBlob(parts);  
  248.                 // Set up and read the blob into an array to be sent  
  249.                 fr = new FileReader();  
  250.                 fr.onload = function() {  
  251.                     oldSend.call(oXHR, fr.result);  
  252.                 };  
  253.                 fr.onerror = function(err) {  
  254.                     throw err;  
  255.                 };  
  256.                 fr.readAsArrayBuffer(data);  
  257.                 // Set the multipart content type and boudary  
  258.                 this.setRequestHeader('Content-Type''multipart/form-data; boundary=' + boundary);  
  259.                 XMLHttpRequest.prototype.send = oldSend;  
  260.             }  
  261.             else {  
  262.                 oldSend.call(this, val);  
  263.             }  
  264.         };  
  265.     }  
  266. </script>  
  267. </body>  
  268. </html>  

 

本文来自于:http://www.yoyo88.cn/study/html5/70.html

Powered by yoyo苏ICP备15045725号