H5照相、预览、紧缩、上传采坑纪录
公司项目前段时间须要完成手机照相上传的功用,原本认为用createObjectURL和canvas能够很轻松的完成,结果发现问题多多,特此纪录下来。
图片预览
在IOS上,竖着照相片时,图片预览会扭转90°,横着照相就没问题,我试验了一下,在IOS上,只有当图片的分辨率过大会涌现这类状况。
末了完成图片预览结果借助了exif-js和megapix-image,exif-js
担任读取图片的EXIF信息,猎取orientation
信息,然后用megapix-image
把图片数据渲染在img标签上,代码以下:
import EXIF from '../utils/exif';
import MegaPixImage from '../utils/megapix-image';
/**
*
* @param file file对象
* @param resImg 预览IMG标签
* @returns {Promise}
*/
renderPreviewImg(file, resImg) {
return new Promise(function (resolve, reject) {
EXIF.getData(file, _=> {
var allMetaData = EXIF.getAllTags(file);
var orientation = allMetaData.Orientation;
var mpImg = new MegaPixImage(file);
mpImg.render(resImg, {
maxWidth: 1024,
maxHeight: 1024,
// quality: 0.6,
orientation: orientation
}, resolve);
});
});
}
无革新紧缩上传
思绪有两种:
用canvas的toDataURL()API,直接将base64文本通报过去
本身组织File对象,ajax上传
第一种要领须要服务器端做事情,而且上传数据量会增大4/3,因而此要领只作为回退计划。
第二种要领的道理是用Uint8Array来组织Blob,再运用formData上传。
这里要注意的是:ArrayBuffer
不能被直接操纵,必需经由过程typed array
来存取,而且Blob的组织函数也是typed array
。
完全代码以下:
this.renderPreviewImg(file, resImg)
.then(() => {
try {
var binaryData = null;
if (!Blob || !ArrayBuffer || !Uint8Array) {
// alert(123);
binaryData = file;//假如不支持紧缩,直接上传原始图片
} else {
//组装二进制
var base64Data = $(resImg).attr('src');
var byteString = atob(base64Data.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);
}
binaryData = new Blob([ia], {
"type": file.type
});
}
this.setState({
uploadProgress: 0
});
//组装formData
var fd = new FormData();
fd.append('file', binaryData, 'img.jpg');
fd.append('token', uploadToken);
console.log(fd);
return this.uploadBinaryDataToQiniu(fd, this.uploadSuccess.bind(this), this.handleUploadProgress.bind(this))
} catch (e) {
alert(e.message);
}
}).catch(function (e) {
console.log(e);
})