最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

H5实现图片压缩与上传

来源:动视网 责编:小OO 时间:2020-11-27 15:05:02
文档

H5实现图片压缩与上传

接到需求,问前端是否可以压缩图片?因为有的图片太大,传到服务器上再压缩太慢了。意识里没有这么玩过,早上老大丢来一个知乎链接,一看,原来前辈们已经用canvas实现了(为自己的见识羞愧3秒钟,再马上开干)。canvas压缩;使用了github上的一个现成库:https://github.com/stomita/ios-imagefile-megapixel,不得不膜拜下stomita这位大神。大体的思路是将图片抽样显示在canvas上,然后用通过canvas.toDataURL方法得到base字符串来实现压缩。比如在input元素触发change事件之后,读取里面的文件进行操作。
推荐度:
导读接到需求,问前端是否可以压缩图片?因为有的图片太大,传到服务器上再压缩太慢了。意识里没有这么玩过,早上老大丢来一个知乎链接,一看,原来前辈们已经用canvas实现了(为自己的见识羞愧3秒钟,再马上开干)。canvas压缩;使用了github上的一个现成库:https://github.com/stomita/ios-imagefile-megapixel,不得不膜拜下stomita这位大神。大体的思路是将图片抽样显示在canvas上,然后用通过canvas.toDataURL方法得到base字符串来实现压缩。比如在input元素触发change事件之后,读取里面的文件进行操作。
 这篇文章主要为大家详细介绍了H5图片压缩与上传的实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

接到需求,问前端是否可以压缩图片?因为有的图片太大,传到服务器上再压缩太慢了。意识里没有这么玩过,早上老大丢来一个知乎链接,一看,原来前辈们已经用canvas实现了(为自己的见识羞愧3秒钟,再马上开干)!。

canvas压缩

使用了github上的一个现成库:https://github.com/stomita/ios-imagefile-megapixel,不得不膜拜下stomita这位大神。大体的思路是将图片抽样显示在canvas上,然后用通过canvas.toDataURL方法得到base字符串来实现压缩。比如在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 base字符串

 uploadBasestr: function (baseStr) {
 var formdata = new FormData();
 formdata.append("basestr", baseStr);
 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.basestrUrl, true);
 xhr.send(formdata);
 },

比如这里basestrUrl是/home/MUploadImgBaseStr,MVC控制器方法如下:

 [HttpPost]
 public ActionResult MUploadImgBaseStr(string basestr)
 {
 try
 {
 var imgData = basestr.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.FromBaseString(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 base1 = resImg.src;

一个是用canvas转换:

 function getBaseImage(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;base,", "");
 }
 var base = getBaseImage(resImg);

同一张图片,这两者获取到的字符串大小不一样,但图片质量我是分辨不出什么差别。

比如一个2M的图片,通过getBaseImage方法读到的字符串大小才k,而src直接读取到的却是270k,各自生成的图片更小。一下分别是原图(2.2M),base(48k),src(202k)对应的图片。

getBaseImage通过canvas的toDataURL 获取到更小的base字符串。

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);
 },

文档

H5实现图片压缩与上传

接到需求,问前端是否可以压缩图片?因为有的图片太大,传到服务器上再压缩太慢了。意识里没有这么玩过,早上老大丢来一个知乎链接,一看,原来前辈们已经用canvas实现了(为自己的见识羞愧3秒钟,再马上开干)。canvas压缩;使用了github上的一个现成库:https://github.com/stomita/ios-imagefile-megapixel,不得不膜拜下stomita这位大神。大体的思路是将图片抽样显示在canvas上,然后用通过canvas.toDataURL方法得到base字符串来实现压缩。比如在input元素触发change事件之后,读取里面的文件进行操作。
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top