H5图片压缩与上传
接到需求,问前端是否可以压缩图片?因为有的图片太大,传到服务器上再压缩太慢了。意识里没有这么玩过,早上老大丢来一个知乎链接,一看,原来前辈们已经用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(',')[];
//过滤特殊字符即可
string dummyData = imgData.Trim().Replace("%", "").Replace(",", "").Replace(" ", "+");
if (dummyData.Length % > )
{
dummyData = dummyData.PadRight(dummyData.Length + - dummyData.Length % , '=');
}
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/
小结:基本上就是这样了,前端能够压缩图片的话,确实省了流量和时间。 插件是在上一篇的基础上进行改进的。
H5图片压缩与上传的更多相关文章
- 项目分享五:H5图片压缩与上传
一.简介 图片的压缩与上传,是APP里一个很常用的功能.我们来年看 ChiTuStore 是怎样做的.相关文件 App/Module/User/UserInfo.html,App/Module/Use ...
- 使用ajax上传图片,支持图片即时浏览,支持js图片压缩后上传给服务器
使用ajax上传图片,支持图片即时浏览,支持js图片压缩后上传给服务器 ajax上传主要使用了 var reader = new FileReader() 此方法 js图片压缩主要是利用canvas进 ...
- (转)Android学习-使用Async-Http实现图片压缩并上传功能
(转)Android学习-使用Async-Http实现图片压缩并上传功能 文章转载自:作者:RyaneLee链接:http://www.jianshu.com/p/940fc7ba39e1 让我头疼一 ...
- 移动端h5拍照压缩即时上传后台并预览
项目经理让迭代一个功能,实时预览并上传到后台的功能,听到这立马想起了几个第三方插件去实现,mui 和api cloude万万没想到的是这个app前面使用ios 和安卓原生写的,然后mui和api c ...
- Android的图片压缩并上传
Android开发中上传图片很常见,一般为了节省流量会进行压缩的操作,本篇记录一下压缩和上传的方法. 图片压缩的方法 : import java.io.ByteArrayOutputStream; i ...
- vue开发中vue-resource + canvas 图片压缩、上传、预览
1.使用vue-resource上传,也可以自定义ajax上传: 2.使用<input type="file" @change="submit()" na ...
- js图片压缩+ajax上传
图片压缩用到了localresizeimg 地址: https://github.com/think2011/localResizeIMG 用起来比较简单 <input type="f ...
- H5图片预览、压缩、上传
目标实现: 1.选择图片, 前端预览效果 2.图片大于1.2M的时候, 对图片进行压缩 3.以表单的形式上传图片 4.图片删除 预览效果图: 代码说明: 1.input:file选择图片 <!- ...
- 基于h5的图片无刷新上传(uploadifive)
基于h5的图片无刷新上传(uploadifive) uploadifive简介 了解uploadify之前,首先了解来一下什么是uploadify,uploadfy官网,uploadify和uploa ...
随机推荐
- Python高手之路【六】python基础之字符串格式化
Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...
- Oracle 的基本操作符
!= 不等于 select empno,ename,job from scott.emp where job!='manager' ^= 不等于 select empno,ename,job from ...
- ABP文档 - 嵌入的资源文件
文档目录 本节内容: 简介 创建嵌入的文件 暴露嵌入的文件 使用嵌入的文件 简介 一个web应用里,客户端包含javascript,css,xml等文件,这此文件被添加到一个web项目后,发布成独立的 ...
- Js 原型和原型链
Js中通过原型和原型链实现了继承 Js对象属性的访问,首先会查找自身是否拥有这个属性 如果查到,则返回属性值,如果找不到,就会遍历原型链,一层一层的查找,如果找到就会返回属性值 直到遍历完Object ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- [干货来袭]MSSQL Server on Linux预览版安装教程(先帮大家踩坑)
前言 昨天晚上微软爸爸开了全国开发者大会,会上的内容,我就不多说了,园子里面很多.. 我们唐总裁在今年曾今透漏过SQL Server love Linux,果不其然,这次开发者大会上就推出了MSSQL ...
- vs15 preview5 离线安装包
1.介绍 vs15是微软打造的新一代IDE,全新的安装方式.官网介绍如下(https://blogs.msdn.microsoft.com/visualstudio/2016/10/05/announ ...
- Entity Framework的启动速度优化
最近开发的服务放到IIS上寄宿之后,遇到一些现象,比如刚部署之后,第一次启动很慢:程序放置一会儿,再次请求也会比较慢.比如第一个问题,可以解释为初次请求某一个服务的时候,需要把程序集加载到内存中可能比 ...
- gRPC源码分析1-SSL/TLS
引子 前几天看到微信后台团队分享了TLS相关文章,正好gRPC里TLS数据加密是很重要的一块,于是整理出了这篇文章. 在gRPC里,如果仅仅是用来做后端微服务,可以考虑不加密.本文太长,先给个大纲. ...
- Android Weekly Notes Issue #235
Android Weekly Issue #235 December 11th, 2016 Android Weekly Issue #235 本期内容包括: 开发一个自定义View并发布为开源库的完 ...