h5图片压缩上传

偏执的太偏执、 2023-08-17 15:47 239阅读 0赞

1、图片上传过慢,图片进行压缩上传

1021765-20190706163117700-599513873.png

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

转载于:https://www.cnblogs.com/congfeicong/p/11143183.html

发表评论

表情:
评论列表 (有 0 条评论,239人围观)

还没有评论,来说两句吧...

相关阅读

    相关 h5图片

    做了一个h5多图片上传 只要了解了 基本原理,那就很好理解了,可以看看注释或者在网上找找原理 <!doctype html> <html>