H5拍照、预览、压缩、上传采坑记录

来源:转载

H5拍照、预览、压缩、上传采坑记录

公司项目前段时间需要实现手机拍照上传的功能,本来以为用createObjectURL和canvas可以很轻松的实现,结果发现问题多多,特此记录下来。


DEMO预览(需用新标签页打开)


图片预览

在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);
})
参考文章

http://tgideas.qq.com/webplat...


http://blog.csdn.net/hsany330...

分享给朋友:
您可能感兴趣的文章:
随机阅读: