前台图片Canvas压缩上传小结
需求来源:之前有个提交审核表单的业务,表单中含有大量附件图片,大约有20多张吧,为了省事,采用的同步上传,一次需要上传很多照片,本来单张图片限制为200KB,这样子总图片大小约为5MB左右,想想也可以接收。业务上线后,得知用户大部分都是中老年人居多,手机拍照的图片很大,不会压缩。放开图片尺寸上传限制后,上传数据太大,体验很不好,就有了前台图片压缩的需求。
业务实现要点:
1、上传的图片使用canvas压缩图片,并导出base64字符串数据;
2、每一类型附件可以传多张图片,这些图片的base64数据存放到hashmap集合中,key值为file的id;
3、后台将接收到图片的base64字符串转存为图片格式。
核心业务代码如下:
-- 前台图片压缩保存
/**
* 存储图片数据
* @param _this
* @param picType
*/
function picStrore(_this,picType) {
var obj = $(_this);
var id = obj.attr('id');// 元素id
// $("#fw_pic_1")[0].files[0] 是否包含文件
var file = $("#"+id)[0].files[0];
if(file){ // 有图片
imgeToBase64_save(file,id,picType); // 保存数据到hashmap
}else{ // 无图片
removeImgdata(id,picType); // 从hashmap中移除数据
}
}
/**
* 将图片转成base64字符串存储hashmap中
* @param file 文件对象
* @param fileId 元素id
* @param picType 文件类型
* @returns {boolean}
*/
function imgeToBase64_save(file,fileId,picType) {
if (!/image\/\w+/.test(file.type)) {
return false;
}
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function (e) {
var img = new Image,
width = 640,quality = 0.8,canvas = document.createElement("canvas"),drawer = canvas.getContext("2d");
img.src = this.result;
img.onload = function () {
// 计算绘图尺寸(重构的图片尺寸宽度显示最大为640,图片质量设置为0.8)
if (img.height > img.width) {
if (img.width < width) {
canvas.width = img.width;
canvas.height = img.height;
} else {
canvas.width = width;
canvas.height = width * (img.height / img.width);
}
} else {
if (img.height < width) {
canvas.width = img.width;
canvas.height = img.height;
} else {
canvas.height = width;
canvas.width = width * (img.width / img.height);
}
}
drawer.drawImage(img, 0, 0, canvas.width, canvas.height);
var tmpsrc = canvas.toDataURL("image/jpeg", quality);
var imgbase64 = tmpsrc.substr(23); // base64字符串
// 保存base64数据到hashmap
if('fw_pic'== picType){ // 房屋所有权证
fw_pic_map.put(fileId,imgbase64);
}else if('td_pic'== picType){ // 国有土地使用权证
td_pic_map.put(fileId,imgbase64);
}else if('bdc_pic'== picType){ // 不动产权证
bdc_pic_map.put(fileId,imgbase64);
}else if('syf_pic'== picType){ // 住房买卖合同
syf_pic_map.put(fileId,imgbase64);
}else if('fp_pic'== picType){ // 购房发票
fp_pic_map.put(fileId,imgbase64);
}else if('sfz_pic'== picType){ // 身份证
sfz_pic_map.put(fileId,imgbase64);
}else if('zl_pic'== picType){ // 户口簿资料页
zl_pic_map.put(fileId,imgbase64);
}else if('gzs_pic'== picType){ // 委托书/公证书/通知书
gzs_pic_map.put(fileId,imgbase64);
}else if('other_pic'== picType){ // 其他材料
other_pic_map.put(fileId,imgbase64);
}
}
}
}
/**
* 从hashmap中移除数据
* @param fileId
* @param picType
*/
function removeImgdata(fileId,picType) {
if('fw_pic'== picType){ // 房屋所有权证
fw_pic_map.remove(fileId);
}else if('td_pic'== picType){ // 国有土地使用权证
td_pic_map.remove(fileId);
}else if('bdc_pic'== picType){ // 不动产权证
bdc_pic_map.remove(fileId);
}else if('syf_pic'== picType){ // 住房买卖合同
syf_pic_map.remove(fileId);
}else if('fp_pic'== picType){ // 购房发票
fp_pic_map.remove(fileId);
}else if('sfz_pic'== picType){ // 身份证
sfz_pic_map.remove(fileId);
}else if('zl_pic'== picType){ // 户口簿资料页
zl_pic_map.remove(fileId);
}else if('gzs_pic'== picType){ // 委托书/公证书/通知书
gzs_pic_map.remove(fileId);
}else if('other_pic'== picType){ // 其他材料
other_pic_map.remove(fileId);
}
}
-- 后台图片保存
/**
* 保存BASE64图片数据
* @param imgStr 图片base64数据
* @param savePath 图片保存路径
*/
public static void saveBase64Img(String imgStr,String savePath) {
if (imgStr == null) //图像数据为空
return;
BASE64Decoder decoder = new BASE64Decoder();
try {
//Base64解码
byte[] b = decoder.decodeBuffer(imgStr);
for(int i=0; i<b.length; ++i) {
if(b[i]<0) {
b[i]+=256; //调整异常数据
}
}
//生成jpeg图片
OutputStream out = new FileOutputStream(savePath);
out.write(b);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
压缩效果:压缩后的图片附件总大小控制在1MB左右。
注:canvas的大小有限制,如果canvas的大小大于大概五百万像素(即宽高乘积)的时候,不仅图片画不出来,其他什么东西也都是画不出来的。
坑:前台上传使用ajax提交请求,但是必须保证enctype = "multipart/form-data",否则post的数据长度会超出限制,使用FormData对象提交请求,具体代码如下:
var formData = new FormData();
formData.append('buyerone',$("#buyerone").val());
formData.append('buyerone_no',$("#buyerone_no").val());
formData.append('buyerone_phone',$("#buyerone_phone").val()); formData.append('buyertwo',$("#buyertwo").val());
formData.append('buyertwo_no',$("#buyertwo_no").val());
formData.append('buyertwo_phone',$("#buyertwo_phone").val()); formData.append('buyerthree',$("#buyerthree").val());
formData.append('buyerthree_no',$("#buyerthree_no").val());
formData.append('buyerthree_phone',$("#buyerthree_phone").val()); formData.append('handler',$("#handler").val());
formData.append('handler_no',$("#handler_no").val());
formData.append('handler_phone',$("#handler_phone").val()); formData.append('remark',$("#remark").val()); formData.append('house_site',$("#house_site").val());
formData.append('house_area',$("#house_area").val());
formData.append('loft_area',$("#loft_area").val());
formData.append('sign_date',$("#sign_date").val());
formData.append('ownership_no',$("#ownership_no").val());
formData.append('landuse_no',$("#landuse_no").val());
formData.append('immovable_no',$("#immovable_no").val()); formData.append('apply_type',$("input[name='apply_type']:checked").val());
formData.append('buy_total',$("#buy_total").val());
formData.append('house_price_v',$("#house_price_v").val());
formData.append('loft_price_v',$("#loft_price_v").val());
formData.append('estimate_total_v',$("#estimate_total_v").val());
formData.append('pay_price_v',$("#pay_price_v").val()); formData.append('fw_pic',fw_pic);
formData.append('td_pic',td_pic);
formData.append('bdc_pic',bdc_pic);
formData.append('syf_pic',syf_pic);
formData.append('fp_pic',fp_pic);
formData.append('sfz_pic',sfz_pic);
formData.append('zl_pic',zl_pic);
formData.append('gzs_pic',gzs_pic);
formData.append('other_pic',other_pic); $.ajax({
url: http_url+"/api/upfile/houseApplyUpload2",
type: "POST",
cache: false,
data: formData,
processData: false,
contentType: false,
dataType: "json",
success: function(res){
var resobj = res;
if(resobj.code=="4901"){ // 上传文件超限
window.parent.layer.alert("上传文件大小超出限制", {icon: 0});
}else if(resobj.code=="0000"){
var data = resobj.data;
var isSuccess = data.isSuccess;
var msg = data.msg;
if(isSuccess==0){ //成功
window.location.href="houseApplyOk.shtml";
}else if(isSuccess==1){// 失败
window.parent.layer.alert(msg, {icon: 0});
}else{ // 异常
window.parent.layer.alert("申请审核表提交失败", {icon: 0});
}
}
window.parent.layer.close(ha_index);// 清除加载
},
error:function(res) {
window.parent.layer.close(ha_index);// 清除加载
}
});
前台图片Canvas压缩上传小结的更多相关文章
- CANVAS运用-对图片的压缩上传(仅针对移动浏览器)
最近在移动端设计头像上传功能时,原本是以<input type="file">直接通过formData上传,然而实际使用情况是:对于过大的图片(高像素手机所拍摄的照片等 ...
- HTML5 图片本地压缩上传插件「localResizeIMG」
移动应用中用户往往需要上传照片,但是用户上传的照片尺寸通常很大,而手机的流量却很有限,所以在上传前对图像进行压缩是很有必要的. 原生应用可以直接对文件进行处理,网页应用就没有这个优势了.不过 canv ...
- uniapp小程序图片前端压缩上传
目录 1,前言 2,实现代码 1,前言 这次项目中做了一个图片上传,要求是大于2MB的就压缩成2MB一下的再上传,我这边利用了uniapp的文件接口,使用canvas做了一个压缩上传的功能,目前已上线 ...
- Html5+asp.net mvc 图片压缩上传
在做图片上传时,大图片如果没有压缩直接上传时间会非常长,因为有的图片太大,传到服务器上再压缩太慢了,而且损耗流量. 思路是将图片抽样显示在canvas上,然后用通过canvas.toDataURL方法 ...
- 三款不错的图片压缩上传插件(webuploader+localResizeIMG4+LUploader)
涉及到网页图片的交互,少不了图片的压缩上传,相关的插件有很多,相信大家都有用过,这里我就推荐三款,至于好处就仁者见仁喽: 1.名气最高的WebUploader,由Baidu FEX 团队开发,以H5为 ...
- Vue directive自定义指令+canvas实现H5图片压缩上传-Base64格式
前言 最近优化项目-手机拍照图片太大,回显速度比较慢,使用了vue的自定义指令实现H5压缩上传base64格式的图片 canvas自定义指令 Vue.directive("canvas&qu ...
- js 图片压缩上传(纯js的质量压缩,非长宽压缩)
下面是大神整理的demo,很实用,这里存一下备用,感谢大神! 此demo为大于1M对图片进行压缩上传 若小于1M则原图上传,可以根据自己实际需求更改. demo源码如下 <!DOCTYPE ht ...
- 前端图片压缩上传(纯js的质量压缩,非长宽压缩)
此demo为大于1M对图片进行压缩上传 若小于1M则原图上传,可以根据自己实际需求更改. demo源码如下: <!DOCTYPE html> <html> <head&g ...
- springMVC多图片压缩上传的实现
首先需要在配置文件中添加配置: <!--配置文件的视图解析器,用于文件上传,其中ID是固定的:multipartResolver--> <bean id="multipar ...
随机推荐
- 071、Java面向对象之使用private封装属性
01.代码如下: package TIANPAN; class Book { // 定义一个新的类 private String title; // 书的名字 private double price ...
- jmeter学习笔记---循环控制器计数器函数助手
循环控制器与计数器,以及函数助手需要配合使用,实现循环 循环控制器的“循环次数”输入最大循环次数的参数 计数器:除输入最大值外,还需要输入“引用名称”,供后续请求使用 请求中,如果需要实现循环,需要借 ...
- 防止SQL注入的登录页面
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/T ...
- 题解 loj2065 「SDOI2016」模式字符串
点分治. 考虑经过当前分治中心\(u\)的点对数量. 这种数点对数的问题,有一个套路.我们可以依次考虑\(u\)的每个儿子,看用当前的儿子,能和之前已经考虑过的所有儿子,组成多少点对.这样所有合法的点 ...
- 12541:TNS无监听状态
上次在项目上遇见数据库报这个问题,然后网上几乎都是让重新进行配置数据库.配置多次之后还是无效,最后找到了问题的根源. 使用的是Oracle数据库,用PLSQL登录报的这个错误. 在计算机全局搜索:li ...
- Rolling Update【转】
滚动更新是一次只更新一小部分副本,成功后,再更新更多的副本,最终完成所有副本的更新.滚动更新的最大的好处是零停机,整个更新过程始终有副本在运行,从而保证了业务的连续性. 下面我们部署三副本应用,初始镜 ...
- 数十万PhpStudy用户被植入后门,快来检测你是否已沦为“肉鸡”!
北京时间9月20日,杭州公安发布<杭州警方通报打击涉网违法犯罪暨‘净网2019’专项行动战果>一文,文章曝光了国内知名PHP调试环境程序集成包“PhpStudy软件”遭到黑客篡改并植入“后 ...
- JDK8~JDK11的新特性
#JDK 1.8 新特性接口中的静态方法 只能由接口自己调用 接口中的默认方法 可以不被覆盖 #JDK 1.9 新特性(可能在JDK8中被忽略了,没来得及加)接口可以定义私有方法,但是只能让自己调用, ...
- 02.swoole学习笔记--UDP服务器
<?php //创建服务器 $serv=,SWOOLE_PROCESS,SWOOLE_SOCK_UDP); //bool $swoole_server->on(string $event, ...
- [题解] LuoguP4091 [HEOI2016/TJOI2016]求和
传送门 首先我们来看一下怎么求\(S(m,n)\). 注意到第二类斯特林数的组合意义就是将\(m\)个不同的物品放到\(n\)个没有区别的盒子里,不允许有空盒子的方案数. 那么将\(m\)个不同的物品 ...