Questions:近期需要做一个需求,关于前端获取图片后压缩,再上传给后台服务器或者上传至oss后将路径传给后台服务器,压缩的时候发现在ios10及以下的系统是无效的,经查证,这是由于使用canvas的 HTMLCanvasElement.toBlob()
方法创造blob对象的时候,ios10及以下系统无法调用。
Answer:
1. 实现前端压缩图片并上传
(1)HTML:图片预览盒子&input上传控件
<div id="uploader">
<!-- 展示预览图片 -->
<!-- <div class="img_show"></div> -->
<!-- 图片上传 -->
<div id="fileInput" class="img_uploader">
<input id="imgUpload" type="file" name="imgs" accept="image/*">
</div>
</div>
(2)图片上传及压缩
// 表单上传的formdata对象
var fd = new FormData();
// 用于压缩图片的canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
var file = null; // 用户上传的图片对象
/* 点击input上传图片 */
$("#fileupload").on('change', function (e) {
file = event.target.files[0];
// 图片预览,加载base64图片
var reader = new FileReader();
reader.onload = (function (file) {
return function (e) {
var datainfo = this.result;
img.src = datainfo;
var html = '<div class="img_show" style="background-image:url('+ datainfo +')"></div>'
$("#uploader").prepend(html);
if ($("#uploader .img_showCurrent").length >= 2) {
$("#fileInput").hide();
}
};
})(e.target.files[0]);
reader.readAsDataURL(e.target.files[0]);
// base64地址图片加载完毕后,绘制canvas压缩图片
img.onload = function () {
// 图片原始尺寸
var originWidth = this.width;
var originHeight = this.height;
// 最大尺寸限制
var maxWidth = 800, maxHeight = 800;
// 目标尺寸
var targetWidth = originWidth, targetHeight = originHeight;
// 图片尺寸超过400x400的限制
if (originWidth > maxWidth || originHeight > maxHeight) {
if (originWidth / originHeight > maxWidth / maxHeight) {
// 更宽,按照宽度限定尺寸
targetWidth = maxWidth;
targetHeight = Math.round(maxWidth * (originHeight / originWidth));
} else {
targetHeight = maxHeight;
targetWidth = Math.round(maxHeight * (originWidth / originHeight));
}
}
// canvas对图片进行缩放
canvas.width = targetWidth;
canvas.height = targetHeight;
// 清除画布
ctx.clearRect(0, 0, targetWidth, targetHeight);
// 图片压缩
ctx.drawImage(img, 0, 0, targetWidth, targetHeight);
// 当canvas对象的原型中没有toBlob方法的时候,手动添加该方法
if (!HTMLCanvasElement.prototype.toBlob) {
Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
value: function (callback, type, quality) {
var binStr = atob( this.toDataURL(type, quality).split(',')[1] ),
len = binStr.length,
arr = new Uint8Array(len);
for (var i=0; i<len; i++ ) {
arr[i] = binStr.charCodeAt(i);
}
callback( new Blob( [arr], {type: type || 'image/png'} ) );
}
});
}
// canvas转为blob并上传
canvas.toBlob(function (blob) {
fd.append('pic', blob)
}, file.type||'image/png');
};
})
(3)上传图片
fd.append("uid", uids);
$.ajax({
type: "post",
url: baseUrl + "xxxx/xxxxx",
data: fd,
dataType: "json",
processData: false, // processData和contentType需设置为false
contentType: false,
async: false,
success: function (res) {
// ... ...
}
})
2. 兼容ios10系统
// 当canvas对象的原型中没有toBlob方法的时候,手动添加该方法
if (!HTMLCanvasElement.prototype.toBlob) {
Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
value: function (callback, type, quality) {
var binStr = atob( this.toDataURL(type, quality).split(',')[1] ),
len = binStr.length,
arr = new Uint8Array(len);
for (var i=0; i<len; i++ ) {
arr[i] = binStr.charCodeAt(i);
}
callback( new Blob( [arr], {type: type || 'image/png'} ) );
}
});
}