前端上传图片正向的图片,上传后就被旋转了。这是因为,图片中包含许多属性来记录拍摄信息。引入EXIF就可以读取这些属性。
引入exif.js文件
exif.js文件下载地址:http://code.ciaoca.com/javascript/exif-js/
载入 JavaScript 文件
<script src="exif.js"></script>
EXIF中,包含一个Orientation参数,用来记录拍摄照片时的方向。在使用PS或者其他软件旋转图片时,图片旋转了,但Orientation不会改变,由于我们使用的图片预览器能够预处理图片,使其看起来与旋转后一致,但上传图片时,浏览器并不会预处理。所以导致图片旋转。
Orientation一共含有8个值,分别是:1、2、3、4、5、6、7、8。
这8个值对应的意思是:
Orientation 释义
1 正常
2 正常镜像
3 顺时针旋转180°
4 顺时针旋转180°镜像
5 顺时针旋转270°镜像
6 顺时针旋转270°
7 顺时针旋转90°镜像
8 顺时针旋转90°
前端通过exif.js文件获取要上传图片的元数据信息Orientation,再通过canvas旋转图片,改变图片的方向再进行上传。
创建Web Uploader实例
// 初始化Web Uploader
var uploader = WebUploader.create({
// 选完文件后,是否自动上传。
auto: true,
// swf文件路径
swf: BASE_URL + '/js/Uploader.swf',
// 文件接收服务端。
server: 'http://webuploader.duapp.com/server/fileupload.php',
// 选择文件的按钮。可选。
// 内部根据当前运行是创建,可能是input元素,也可能是flash.
pick: '#filePicker',
// 只允许选择图片文件。
accept: {
title: 'Images',
extensions: 'gif,jpg,jpeg,bmp,png',
mimeTypes: 'image/*'
}
});
在Web Uploader实例里添加onFileQueued事件
uploader.onFileQueued = function( file ) {
fileCount++;
fileSize += file.size;
if ( fileCount === 1 ) {
$placeHolder.addClass( 'element-invisible' );
$statusBar.show();
}
var Orientation = 0;
var fileExif = file.source.source;
var fileName = fileExif.name;
var newFile = null;
//图片方向角
var rFilter = /^(image\/jpeg|image\/png|image\/jpg|image\/gif|image\/jpe)$/i; // 检查图片格式
if (rFilter.test(file.type) && file.source.source !== undefined) {
console.log("旋转开始");
EXIF.getData(file.source.source, function() {
Orientation = EXIF.getTag(this, 'Orientation');
if (fileExif && Orientation > 1) {
//获取照片方向角属性,用户旋转控制
console.log(Orientation);
var oReader = new FileReader();
oReader.readAsDataURL(fileExif);
oReader.onload = function(e) {
var image = new Image();
image.src = e.target.result;
image.onload = function() {
var expectWidth = this.naturalWidth;
var expectHeight = this.naturalHeight;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = expectWidth;
canvas.height = expectHeight;
ctx.drawImage(this, 0, 0, expectWidth, expectHeight);
var base64 = null;
//修复ios
if (navigator.userAgent.match(/iphone/i)) {
console.log('iphone');
if(Orientation != "" && Orientation != 1){
switch(Orientation){
case 6:
rotateImg(this,'left',canvas);
break;
case 8:
rotateImg(this,'right',canvas);
break;
case 3:
rotateImg(this,'right',canvas);//转两次
rotateImg(this,'right',canvas);
break;
}
}
base64 = canvas.toDataURL(fileExif.type, 1);
}else if (navigator.userAgent.match(/Android/i)) {// 修复android
var encoder = new JPEGEncoder();
base64 = encoder.encode(ctx.getImageData(0, 0, expectWidth, expectHeight), 80);
}else{
if(Orientation != "" && Orientation != 1){
switch(Orientation){
case 6:
rotateImg(this,'left',canvas);
break;
case 8:
rotateImg(this,'right',canvas);
break;
case 3:
rotateImg(this,'right',canvas);//转两次
rotateImg(this,'right',canvas);
break;
}
}
base64 = canvas.toDataURL(fileExif.type, 1);
}
var baseFile = dataURLtoFile(base64, fileName);
newFile = baseFile;
file.source.source = newFile;
addFile(file);
setState('ready');
updateTotalProgress();
};
};
}else {
addFile( file );
setState( 'ready' );
updateTotalProgress();
}
});
} else {
addFile( file );
setState( 'ready' );
updateTotalProgress();
}
function dataURLtoFile(dataurl, filename) { //将base64转换为文件
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 File([u8arr], filename,{
type: mime
});
}
function rotateImg(img, direction,canvas) {
//alert(img);
//最小与最大旋转方向,图片旋转4次后回到原方向
var min_step = 0;
var max_step = 3;
//var img = document.getElementById(pid);
if (img == null)return;
//img的高度和宽度不能在img元素隐藏后获取,否则会出错
var height = img.height;
var width = img.width;
//var step = img.getAttribute('step');
var 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);
}
//旋转角度以弧度值为参数
var degree = step * 90 * Math.PI / 180;
var ctx = canvas.getContext('2d');
switch (step) {
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;
}
}
};
这样上传到后端服务器的图片的Orientation就全部为1啦,预览时,图片就不会被旋转。