H5图片压缩与上传实例
发布时间 - 2026-01-11 00:45:58 点击率:次接到需求,问前端是否可以压缩图片?因为有的图片太大,传到服务器上再压缩太慢了。意识里没有这么玩过,早上老大丢来一个知乎链接,一看,原来前辈们已经用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/
小结:基本上就是这样了,前端能够压缩图片的话,确实省了流量和时间。 插件是在上一篇的基础上进行改进的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# H5
# 压缩
# 上传
# vuejs开发组件分享之H5图片上传、压缩及拍照旋转的问题处理
# H5上传本地图片并预览功能
# H5手机端多文件上传预览插件
# 移动端利用H5实现压缩图片上传功能
# vue中用H5实现文件上传的方法实例代码
# H5移动端图片压缩上传开发流程
# H5移动开发Ajax上传多张Base64格式图片到服务器
# 利用H5特性FormData实现不刷新文件上传
# H5实现手机拍照和选择上传功能
# 创建一个
# 更小
# 自己的
# 的是
# 是一个
# 我是
# 这一
# 是在
# 你可以
# 却是
# 不出
# 基础上
# 这是一个
# 太大
# 大神
# 不存在
# 会很
# 上一篇
# 报错
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
iOS中将个别页面强制横屏其他页面竖屏
Laravel如何处理和验证JSON类型的数据库字段
,南京靠谱的征婚网站?
如何用狗爹虚拟主机快速搭建网站?
JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)
Python自然语言搜索引擎项目教程_倒排索引查询优化案例
Win11怎么关闭资讯和兴趣_Windows11任务栏设置隐藏小组件
如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?
Laravel如何使用Socialite实现第三方登录?(微信/GitHub示例)
最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?
打造顶配客厅影院,这份100寸电视推荐名单请查收
太平洋网站制作公司,网络用语太平洋是什么意思?
如何快速搭建高效WAP手机网站?
图册素材网站设计制作软件,图册的导出方式有几种?
如何挑选最适合建站的高性能VPS主机?
详解vue.js组件化开发实践
b2c电商网站制作流程,b2c水平综合的电商平台?
北京专业网站制作设计师招聘,北京白云观官方网站?
Laravel Admin后台管理框架推荐_Laravel快速开发后台工具
如何在Windows环境下新建FTP站点并设置权限?
ai格式如何转html_将AI设计稿转换为HTML页面流程【页面】
手机软键盘弹出时影响布局的解决方法
Laravel怎么实现API接口鉴权_Laravel Sanctum令牌生成与请求验证【教程】
小视频制作网站有哪些,有什么看国内小视频的网站,求推荐?
湖南网站制作公司,湖南上善若水科技有限公司做什么的?
Laravel Eloquent访问器与修改器是什么_Laravel Accessors & Mutators数据处理技巧
标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析
Laravel用户密码怎么加密_Laravel Hash门面使用教程
js实现获取鼠标当前的位置
WEB开发之注册页面验证码倒计时代码的实现
高防服务器:AI智能防御DDoS攻击与数据安全保障
如何在阿里云香港服务器快速搭建网站?
Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧
Laravel请求验证怎么写_Laravel Validator自定义表单验证规则教程
高防服务器租用指南:配置选择与快速部署攻略
Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】
Laravel Vite是做什么的_Laravel前端资源打包工具Vite配置与使用
Win11关机界面怎么改_Win11自定义关机画面设置【工具】
网站图片在线制作软件,怎么在图片上做链接?
如何在HTML表单中获取用户输入并结合JavaScript动态控制复利计算循环
网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?
怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?
如何在沈阳梯子盘古建站优化SEO排名与功能模块?
音乐网站服务器如何优化API响应速度?
绝密ChatGPT指令:手把手教你生成HR无法拒绝的求职信
网站制作价目表怎么做,珍爱网婚介费用多少?
Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控
长沙做网站要多少钱,长沙国安网络怎么样?
黑客如何利用漏洞与弱口令入侵网站服务器?
北京企业网站设计制作公司,北京铁路集团官方网站?

