之前有开发过用户上传图片的功能(用户手机拍照的图片往往最少都有2M),当时使用了百度团队的 webupload, 自带压缩图片功能,后来一直想要整理个简单的图片压缩工具,这次趁着项目需要,在网上搜索了下,整理出如下代码。

这是一个图片压缩工具,在success回调中可以拿到压缩后的canvas和base64图片数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/**
* 这是基于html5的前端图片压缩工具。
*/
export function ImageResizer(opts) {
var settings = {
resizeMode: "auto" //压缩模式,总共有三种 auto,width,height auto表示自动根据最大的宽度及高度等比压缩,width表示只根据宽度来判断是否需要等比例压缩,height类似。
,
dataSource: "" //数据源。数据源是指需要压缩的数据源,有三种类型,image图片元素,base64字符串,canvas对象,还有选择文件时候的file对象。。。
,
dataSourceType: "image" //image base64 canvas file
,
maxWidth: 150 //允许的最大宽度
,
maxHeight: 200 //允许的最大高度。
,
onTmpImgGenerate: function (img) {} //当中间图片生成时候的执行方法。。这个时候请不要乱修改这图片,否则会打乱压缩后的结果。
,
success: function (resizeImgBase64, canvas) {

} //压缩成功后图片的base64字符串数据。
,
...opts // 自定义设置覆盖默认设置
};
var innerTools = {
getBase64FromImgFile: function (file, callBack) {
var reader = new FileReader();
reader.onload = function (e) {
var base64Img = e.target.result;
if (callBack) {
callBack(base64Img);
}
};
reader.readAsDataURL(file);
},
//--处理数据源。。。。将所有数据源都处理成为图片对象,方便处理。
getImgFromDataSource: function (datasource, dataSourceType, callback) {
var _me = this;
var img1 = new Image();
if (dataSourceType == "img" || dataSourceType == "image") {
img1.src = $(datasource).attr("src");
if (callback) {
callback(img1);
}
} else if (dataSourceType == "base64") {
img1.src = datasource;
if (callback) {
callback(img1);
}
} else if (dataSourceType == "canvas") {
img1.src = datasource.toDataURL("image/jpeg");
if (callback) {
callback(img1);
}
} else if (dataSourceType == "file") {
_me.getBase64FromImgFile(function (base64str) {
img1.src = base64str;
if (callback) {
callback(img1);
}
});
}

},
//计算图片的需要压缩的尺寸。当然,压缩模式,压缩限制直接从setting里面取出来。
getResizeSizeFromImg: function (img) {
var _img_info = {
w: img.width,
h: img.height
};
// console.log("真实尺寸:", _img_info);
var _resize_info = {
w: 0,
h: 0
};
if (_img_info.w <= settings.maxWidth && _img_info.h <= settings.maxHeight) {
return _img_info;
}
if (settings.resizeMode == "auto") {
var _percent_scale = parseFloat(_img_info.w / _img_info.h);
var _size1 = {
w: 0,
h: 0
};
var _size_by_mw = {
w: settings.maxWidth,
h: parseInt(settings.maxWidth / _percent_scale)
};
var _size_by_mh = {
w: parseInt(settings.maxHeight * _percent_scale),
h: settings.maxHeight
};
if (_size_by_mw.h <= settings.maxHeight) {
return _size_by_mw;
}
if (_size_by_mh.w <= settings.maxWidth) {
return _size_by_mh;
}
return {
w: settings.maxWidth,
h: settings.maxHeight
};
}
if (settings.resizeMode == "width") {
if (_img_info.w <= settings.maxWidth) {
return _img_info;
}
var _size_by_mw = {
w: settings.maxWidth,
h: parseInt(settings.maxWidth / _percent_scale)
};
return _size_by_mw;
}
if (settings.resizeMode == "height") {
if (_img_info.h <= settings.maxHeight) {

return _img_info;
}
var _size_by_mh = {
w: parseInt(settings.maxHeight * _percent_scale),
h: settings.maxHeight
};
return _size_by_mh;
}
},
//--将相关图片对象画到canvas里面去。
drawToCanvas: function (img, theW, theH, realW, realH, callback) {
var canvas = document.createElement("canvas");
canvas.width = theW;
canvas.height = theH;
var ctx = canvas.getContext('2d');
ctx.drawImage(img,
0, //sourceX,
0, //sourceY,
realW, //sourceWidth,
realH, //sourceHeight,
0, //destX,
0, //destY,
theW, //destWidth,
theH //destHeight
);
//--获取base64字符串及canvas对象传给success函数。
var base64str = canvas.toDataURL("image/png");
if (callback) {
callback(base64str, canvas);
}
}
};

//--开始处理。
(function () {
innerTools.getImgFromDataSource(settings.dataSource, settings.dataSourceType, function (_tmp_img) {
var __tmpImg = _tmp_img;
settings.onTmpImgGenerate(_tmp_img);
//--计算尺寸。
var _limitSizeInfo = innerTools.getResizeSizeFromImg(__tmpImg);
// console.log(_limitSizeInfo);
var _img_info = {
w: __tmpImg.width,
h: __tmpImg.height
};
innerTools.drawToCanvas(__tmpImg, _limitSizeInfo.w, _limitSizeInfo.h, _img_info.w, _img_info.h, function (
base64str, canvas) {
settings.success(base64str, canvas); // 最终回调
});
});
})();

return {};
};
export function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime
});
}

你问我使用方法?自己看代码呀。什么你急着用没时间看?好吧,我大概写下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import { ImageResizer, dataURLtoBlob } from '../utils/imageResizer';
var reader = new FileReader();
reader.onload = function(e) {
var base64Img= e.target.result;
// document.getElementById('preview').src = base64Img;
// 根据base64数据大小判断是否需要压缩
if (base64Img.length>300000) {
var _ir=ImageResizer({
resizeMode:"auto"
,dataSource:base64Img
,dataSourceType:"base64"
,maxWidth: 500 //允许的最大宽度
,maxHeight: 100000 //允许的最大高度。
,onTmpImgGenerate:function(img){}
,success:function(resizeImgBase64,canvas){
// 这里处理已经压缩后的图片数据,将压缩后的图片上传到服务器。
var data = uploadImg(resizeImgBase64);
// data.url...
}
});
} else {
uploadImg(base64Img);
}
};
// 将base64的图片数据转化为formdata中的img上传到服务器
var uploadImg = (base64Img) => {
var blob = dataURLtoBlob(base64Img);
var formdata=new FormData();
formdata.append("img", blob, "image.png");
// 这里只是例子,真实情况请根据使用的工具框架灵活调整。
return request('/Tool/uploadImg', {
method: 'post',
body: formdata
});
}
// file 为所选的图片文件类
reader.readAsDataURL(file);

更新一下,上面的方法,在图片超过2M的情况下,只适合android手机,IOS系统请参考ios-imagefile-megapixel,这个项目把IOS系统拍照的方向问题也一并解决了.