这次给大家带来用HTML5实现图片压缩与上传,HTML5实现图片压缩与上传的注意事项有哪些,下面就是实战案例,一起来看一下。
canvas压缩
使用了github上的一个现成库:https://github.com/stomita/ios-imagefile-megapixel,不得不膜拜下stomita这位大神。大体的思路是将图片抽样显示在canvas上,然后用通过canvas.toDataURL方法得到base64字符串来实现压缩。比如在input元素触发change事件之后,读取里面的文件进行操作:
1 2 3 | fileInput = document.getElementById( 'fileInput' = file = fileInput.files[0
mpImg =
resImg = document.getElementById( 'resultImage'
|
登录后复制
压缩完成会得到类似这样的图片:

data:image/jpeg 这样的格式已经应用的很多了,很多样式里面的背景图片直接就是这样。
需要说明的是有两点,这里的resImg是一个预览图片,是已经存在于文档中的,如果你不需要预览,而只是创建一个img用来压缩(document.createElement("img")),这会少一个tagName属性。你可以修改源码或者自己加上这个属性。源码中会根据tagName进行判断,不存在的话会报错:
1 2 3 4 5 6 7 8 9 10 11 12 13 | MegaPixImage.prototype.render = function (target, options, callback) {
target.tagName = target.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);
}
};
|
登录后复制
另外这是一个耗时的操作,如果是多张图片进行压缩,不能直接调用,需要稍微变换一下,不然会导致前面的图片没有压缩完成就进入到了后面的图片。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 () {
});
})(item);
}
core.previewImage(item);
}
},
|
登录后复制
上传处理
1.直接post base64字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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控制器方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | [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:
1 | var base641 = resImg.src;
|
登录后复制
一个是用canvas转换:
1 2 3 4 | 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;
|
登录后复制
同一张图片,这两者获取到的字符串大小不一样,但图片质量我是分辨不出什么差别。

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

getBase64Image通过canvas的toDataURL 获取到更小的base64字符串。
2.也可以在前端转换blob对象,再post到后端
1 2 3 |
byteString = atob(dataUrl.split( ',' )[1
ab = ia = ( i = 0; i < byteString.length; i++= Blob([ab], { type: 'image/jpeg'
|
登录后复制
3.不压缩的就直接装到formdata中,send到后台。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | uploadFile: function (file) {
console.log( "开始上传" ); var formdata = new FormData();
formdata.append(para.filebase, file);
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);
},
|
登录后复制
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
怎样阻止JS的冒泡和浏览器的默认行为
js与canvas合成图片做出微信公众号海报功能
checkbox在jQuery中的使用
DataTable插件可以实现异步加载吗?
以上是用HTML5实现图片压缩与上传的详细内容。更多信息请关注PHP中文网其他相关文章!