国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

H5圖片壓縮與上傳實例

2019-11-19 16:46:26
字體:
來源:轉載
供稿:網友

接到需求,問前端是否可以壓縮圖片?因為有的圖片太大,傳到服務器上再壓縮太慢了。意識里沒有這么玩過,早上老大丟來一個知乎鏈接,一看,原來前輩們已經用canvas實現了(為自己的見識羞愧3秒鐘,再馬上開干)!。

canvas壓縮

使用了github上的一個現成庫:https://github.com/stomita/ios-imagefile-megapixel,不得不膜拜下stomita這位大神。大體的思路是將圖片抽樣顯示在canvas上,然后用通過canvas.toDataURL方法得到base64字符串來實現壓縮。比如在input元素觸發change事件之后,讀取里面的文件進行操作:

var fileInput = document.getElementById('fileInput'); fileInput.onchange = function() { var file = fileInput.files[0]; // 創建一個壓縮對象,該構造函數接收file或者blob。 var mpImg = new MegaPixImage(file); // render方法的maxWith,maxHeight,以及quality都決定了壓縮圖片的質量 var resImg = document.getElementById('resultImage'); mpImg.render(resImg, { maxWidth: 300, maxHeight: 300, quality: 0.5 });  };壓縮完成會得到

類似這樣的圖片:

data:image/jpeg 這樣的格式已經應用的很多了,很多樣式里面的背景圖片直接就是這樣。

需要說明的是有兩點,這里的resImg是一個預覽圖片,是已經存在于文檔中的,如果你不需要預覽,而只是創建一個img用來壓縮(document.createElement("img")),這會少一個tagName屬性。你可以修改源碼或者自己加上這個屬性。源碼中會根據tagName進行判斷,不存在的話會報錯:

 MegaPixImage.prototype.render = function (target, options, callback) {  //....  target.tagName = target.tagName || "IMG"; //加上這一句  var tagName = target.tagName.toLowerCase();  if (tagName === 'img') {   target.src = renderImageToDataURL(this.srcImage, opt, doSquash);  } else if (tagName === 'canvas') {   renderImageToCanvas(this.srcImage, target, opt, doSquash);  }  if (typeof this.onrender === 'function') {   this.onrender(target);  }  if (callback) {   callback();  }  if (this.blob) {   this.blob = null;   URL.revokeObjectURL(this.srcImage.src);  } };

另外這是一個耗時的操作,如果是多張圖片進行壓縮,不能直接調用,需要稍微變換一下,不然會導致前面的圖片沒有壓縮完成就進入到了后面的圖片。

 fileSelected: function () {     var files = $("#fileImage")[0].files;     var count = files.length;     console.log("共有" + count + "個文件");     for (var i = 0; i < count; i++) {var item = files[i];      console.log("原圖片大小", item.size);      if (item.size > 1024 * 1024 * 2) {       console.log("圖片大于2M,開始進行壓縮...");       (function(img) {        var mpImg = new MegaPixImage(img);        var resImg = document.createElement("img");        resImg.file = img;        mpImg.render(resImg, { maxWidth: 500, maxHeight: 500, quality: 1 }, function() {         //do some thing        });       })(item);      }       core.previewImage(item);     }    },

上傳處理

 1.直接post base64字符串

 uploadBase64str: function (base64Str) {     var formdata = new FormData();     formdata.append("base64str", base64Str);     var xhr = new XMLHttpRequest();     xhr.upload.addEventListener("progress", function (e) {      var percentComplete = Math.round(e.loaded * 100 / e.total);      para.onProgress(percentComplete.toString() + '%');     });     xhr.addEventListener("load", function (e) {      para.uploadComplete(xhr.responseText);     });     xhr.addEventListener("error", function (e) {      para.uploadError(e);     });     xhr.open("post", para.base64strUrl, true);     xhr.send(formdata);    },

比如這里base64strUrl是/home/MUploadImgBase64Str,MVC控制器方法如下:

 [HttpPost]  public ActionResult MUploadImgBase64Str(string base64str)  {   try   {    var imgData = base64str.Split(',')[1];    //過濾特殊字符即可     string dummyData = imgData.Trim().Replace("%", "").Replace(",", "").Replace(" ", "+");    if (dummyData.Length % 4 > 0)    {     dummyData = dummyData.PadRight(dummyData.Length + 4 - dummyData.Length % 4, '=');    }    byte[] byteArray = Convert.FromBase64String(dummyData);    using (System.IO.MemoryStream ms = new System.IO.MemoryStream(byteArray))    {     var img = System.Drawing.Image.FromStream(ms);     var path = "~/Content/UploadFiles/mobile/";     var uploadpath = Server.MapPath(path);     if (!Directory.Exists(uploadpath))     {      Directory.CreateDirectory(uploadpath);     }     var saveName = uploadpath + “stoneniqiu” + ".jpg";     img.Save(saveName);     return Json(saveName);    }   }   catch (Exception e)   {    return Json(e.Message);   }  }

幾M的圖片能壓縮到幾十k或者幾百k,當然,如果寬度、高度和質量設置的太小,圖片就會很失真了。這個字符串怎么獲取呢?有兩個方法,一個是直接讀取src:

 var base641 = resImg.src;

一個是用canvas轉換:

 function getBase64Image(img) {    var canvas = document.createElement("canvas");    canvas.width = img.width;    canvas.height = img.height;    var ctx = canvas.getContext("2d");    ctx.drawImage(img, 0, 0, img.width, img.height);    var dataURL = canvas.toDataURL("image/jpeg");    return dataURL;    // return dataURL.replace("data:image/png;base64,", "");   } var base64 = getBase64Image(resImg);

同一張圖片,這兩者獲取到的字符串大小不一樣,但圖片質量我是分辨不出什么差別。

比如一個2M的圖片,通過getBase64Image方法讀到的字符串大小才64k,而src直接讀取到的卻是270k,各自生成的圖片更小。一下分別是原圖(2.2M),base64(48k),src(202k)對應的圖片。

getBase64Image通過canvas的toDataURL 獲取到更小的base64字符串。

2.也可以在前端轉換blob對象,再post到后端

 function dataURItoBlob(dataUrl) {        var byteString = atob(dataUrl.split(',')[1]);    var ab = new ArrayBuffer(byteString.length);    var ia = new Uint8Array(ab);    for (var i = 0; i < byteString.length; i++) {     ia[i] = byteString.charCodeAt(i);    }    return new Blob([ab], { type: 'image/jpeg' });   }

3.不壓縮的就直接裝到formdata中,send到后臺。

 uploadFile: function (file) {     console.log("開始上傳");     var formdata = new FormData();     formdata.append(para.filebase, file);//這個名字要和mvc后臺配合     var xhr = new XMLHttpRequest();     xhr.upload.addEventListener("progress", function (e) {      var percentComplete = Math.round(e.loaded * 100 / e.total);      para.onProgress(percentComplete.toString() + '%');     });     xhr.addEventListener("load", function (e) {      para.uploadComplete(xhr.responseText);     });     xhr.addEventListener("error", function (e) {      para.uploadError(e);     });     xhr.open("post", para.url, true);      xhr.send(formdata);    },

全部的代碼:(包含壓縮和上傳以及demo):

github:https://github.com/stoneniqiu/h5upload/

小結:基本上就是這樣了,前端能夠壓縮圖片的話,確實省了流量和時間。 插件是在上一篇的基礎上進行改進的。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 辽宁省| 内乡县| 久治县| 长春市| 三河市| 东乡| 九江市| 乐都县| 石景山区| 庐江县| 织金县| 松潘县| 南丰县| 蓝田县| 怀安县| 衡阳县| 海原县| 蓬莱市| 和平县| 邹城市| 徐闻县| 恩施市| 乐亭县| 崇阳县| 昭苏县| 大埔区| 高州市| 禹州市| 梁平县| 礼泉县| 化州市| 肥东县| 邵阳县| 云阳县| 吕梁市| 永嘉县| 耿马| 乌拉特前旗| 镶黄旗| 东莞市| 南乐县|