项目是react使用的是antd-mobile和es6开发,iOS中上传图片被旋转了90度,这里解决后记录下
1、exif获取图片信息并旋转
首先使用exif对图片进行了翻转,上传的图片好了.
import * as exif from "exif-js";
selectFileImage(files: { file: any; orientation: number; url: string; info: WebUploader.File }[], type: string, index: number) {
let fileArr = [] as any;
let _this = this;
// let file = fileObj.files[0];
files &&
files.map((item, index) => {
let file = item.file,
Orientation = null;
if (file) {
exif.getData(file, function() {
exif.getAllTags(this);
Orientation = exif.getTag(this, "Orientation");
// console.log(Orientation, this);
// alert(Orientation);
});
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(e) {
let image = new Image();
image.src = e.target!.result;
image.onload = function() {
let expectWidth = this.naturalWidth;
let expectHeight = this.naturalHeight;
if (this.naturalWidth > this.naturalHeight && this.naturalWidth > 800) {
expectWidth = 800;
expectHeight = (expectWidth * this.naturalHeight) / this.naturalWidth;
} else if (this.naturalHeight > this.naturalWidth && this.naturalHeight > 1200) {
expectHeight = 1200;
expectWidth = (expectHeight * this.naturalWidth) / this.naturalHeight;
}
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
canvas.width = expectWidth;
canvas.height = expectHeight;
ctx.drawImage(this, 0, 0, expectWidth, expectHeight);
let base64 = null;
// 修复ios
let u = navigator.userAgent;
if (u.match(/iphone/i)) {
if (Orientation !== "") {
// alert('旋转处理');
switch (Orientation as any) {
case 6: // 需要顺时针(向左)90度旋转
// alert('需要顺时针(向左)90度旋转');
// _this.rotateImg(this, "left", canvas);
break;
case 8: // 需要逆时针(向右)90度旋转
// alert('需要顺时针(向右)90度旋转');
_this.rotateImg(this, "right", canvas);
break;
case 3: // 需要180度旋转
// alert('需要180度旋转');
_this.rotateImg(this, "right", canvas); // 转两次
_this.rotateImg(this, "right", canvas);
break;
default:
break;
}
/*var mpImg = new MegaPixImage(image);
mpImg.render(canvas, {
maxWidth: 800,
maxHeight: 1200,
quality: 0.8,
orientation: 8
});*/
base64 = canvas.toDataURL("image/jpeg", 0.8);
let imageFile = _this.dataURLtoFile(base64, new Date().getTime());
item.file = imageFile;
fileArr.push(item);
// console.log(fileArr, files)
if (index === files.length - 1) {
// alert("start")
_this.myOnChange(fileArr, type, index);
}
}
} else if (u.indexOf("Android") > -1 || u.indexOf("Adr") > -1) {
alert(Orientation);
// android可以直接不变
if (Orientation !== "") {
// alert('旋转处理');
switch (Orientation as any) {
case 6: // 需要顺时针(向左)90度旋转
// alert('需要顺时针(向左)90度旋转');
_this.rotateImg(this, "left", canvas);
break;
case 8: // 需要逆时针(向右)90度旋转
// alert('需要顺时针(向右)90度旋转');
_this.rotateImg(this, "right", canvas);
break;
case 3: // 需要180度旋转
// alert('需要180度旋转');
_this.rotateImg(this, "right", canvas); // 转两次
_this.rotateImg(this, "right", canvas);
break;
default:
break;
}
/*var mpImg = new MegaPixImage(image);
mpImg.render(canvas, {
maxWidth: 800,
maxHeight: 1200,
quality: 0.8,
orientation: 8
});*/
base64 = canvas.toDataURL("image/jpeg", 0.8);
let imageFile = _this.dataURLtoFile(base64, new Date().getTime());
item.file = imageFile;
fileArr.push(item);
// console.log(fileArr, files)
if (index === files.length - 1) {
// alert("start")
_this.myOnChange(fileArr, type, index);
}
}
}
};
};
} else {
fileArr.push(item);
}
});
}
dataURLtoFile(dataurl: string, filename: string) {
const arr = dataurl.split(","),
mime = arr![0]!.match(/:(.*?);/)![1],
bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, { type: mime });
}
// 对图片旋转处理 added by lzk
rotateImg(img, direction, canvas) {
// alert(img);
// 最小与最大旋转方向,图片旋转4次后回到原方向
let min_step = 0;
let max_step = 3;
// var img = document.getElementById(pid);
if (img == null) return;
// img的高度和宽度不能在img元素隐藏后获取,否则会出错
let height = img.height;
let width = img.width;
// var step = img.getAttribute('step');
let step = 2;
if (step == null) {
step = min_step;
}
if (direction === "right") {
step++;
// 旋转到原位置,即超过最大值
step > max_step && (step = min_step);
} else {
step--;
step < min_step && (step = max_step);
}
// 旋转角度以弧度值为参数
let degree = (step * 90 * Math.PI) / 180;
let ctx = canvas.getContext("2d");
switch (step as any) {
case 0:
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0);
break;
case 1:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, 0, -height);
break;
case 2:
canvas.width = width;
canvas.height = height;
ctx.rotate(degree);
ctx.drawImage(img, -width, -height);
break;
case 3:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, -width, 0);
break;
default:
break;
}
}
onChange(files: { file: any; orientation: number; url: string; info: WebUploader.File }[], type: string, index: number) {
const { fileNumLimit } = this.props;
if (files.length > fileNumLimit) {
Toast.fail("文件数量超过限制!", 3);
return;
}
if (this.props.fileSuccess) {
// 有回调就执行,企业认证表单提交会调用
this.props.fileSuccess(files);
}
console.log("onChange", files, type)
if (type === "add") {
this.selectFileImage(files, type, index);
} else if (type === "remove") {
const { files: old } = this.state,
file = old[index],
{ info = file } = file as any;
this.attachProvider.delFile(info.file || info, this.uploader);
this.setState({ files } as any);
}
}
myOnChange(files: { file: any; orientation: number; url: string; info: WebUploader.File }[], type: string, index: number) {
if (this.props.single) {
const file = files.last();
this.uploader.once("fileQueued", (info: WebUploader.File) => (((file.info = info), ((info as any).src = file)), this.setState({ files: [file] } as any)));
this.uploader.addFile(file.file);
} else {
files.map((file, index) => {
files
alert(file.orientation)
if (index >= this.state.files.length) {
setTimeout(() => {
this.uploader.once("fileQueued", (info: WebUploader.File) => (((file.info = info), ((info as any).src = file)), this.setState({ files: files } as any)));
this.uploader.addFile(file.file);
});
}
});
}
}
2、新的问题
后面出现了新的问题,上传后没问题但是蚂蚁组件ImagePicker的预览图里还是翻转的,排查蚂蚁组件的file如下,发现这里面有个orientation还记录着旋转信息
手动给这个值附上假的旋转信息,这样蚂蚁组件ImagePicker就不会自己翻转了
files && files.length && files.map((file, index) => {
file.orientation = 1
});
3、其他发现,采用服务端进行翻转
详细处理方法如下
苹果手机iOS9.0以后图片就会自动正过来但是图片exif方向还是标记了旋转90度。
后面因为性能问题图片处理放在服务端处理分成iOS和安卓两种
1、iOS如果方向值是6,不用进行图片翻转,但是抹除图片exif中翻转信息为1
2、安卓如果方向值是6,按规定进行翻转并重置exif中翻转信息为1