IOS这个照片横屏问题相信困扰了不少程序猿,作者当时也是寻找各种解决办法,前端处理试过,后端处理也试过,base64也用过,无奈没有更好的方法,今天这个问题可以说是完美解决了,废话不多说 直接撸代码
这是html部分
<div class="test">
<img src="" width="200" height="200" class="img">
<img src="" width="200" height="200" class="img2">
<input type="file" name="img" class="imgs" οnchange="imgdata(event)">
<button type="button" class="sub">提交</button>
</div>
这是js部分
//input:file change事件
function imgdata(obj) {
var e4e = getObjectURL(obj.target.files[0]);
$(".img2").attr('src',e4e);
var readerFiles = obj.target.files[0];
console.log(readerFiles);
photoCompress(readerFiles,{quality: 0.8},
function(base64Codes) {
$(".img").attr('src', base64Codes);
}
)
}
//获取上传图片并处理成正常的图片
function photoCompress(file,w,objDiv) {
var ready = new FileReader();
/*开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.*/
ready.readAsDataURL(file);
ready.onload = function() {
var re = this.result;
canvasDataURL(re,w, objDiv)
}
}
//获取上传图片的Orientation并旋转
function canvasDataURL(path,w, callback) {
var img = new Image();
var canvas = document.createElement("canvas");
img.onload = function() {
EXIF.getData(this, function() {
Orientation = EXIF.getTag(this, 'Orientation');
//如果方向角不为1,都需要进行旋转
if (Orientation != "" && Orientation != 1 && Orientation) {
switch (Orientation) {
case 6: //需要顺时针(向左)90度旋转
console.log(66);
rotateImg(this, 'left', canvas,w, callback);
break;
case 8: //需要逆时针(向右)90度旋转
rotateImg(this, 'right', canvas,w, callback);
break;
case 3: //需要180度旋转
rotateImg(this, 'right', canvas,w, callback); //转两次
rotateImg(this, 'right', canvas,w, callback);
break;
}
} else {
callback(path);
}
});
}
img.src = path;
}
//根据Orientation旋转图片,生成base64的文件
function rotateImg(img, direction, canvas, w,callback3) {
//最小与最大旋转方向,图片旋转4次后回到原方向
var min_step = 0;
var max_step = 3;
if (img == null) return;
//img的高度和宽度不能在img元素隐藏后获取,否则会出错
var height = img.height;
var width = img.width;
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;
}
dat = canvas.toDataURL("image/jpeg", w.quality);
callback3(dat)
};
//将base64图片转换成文件形式 后台用$_FILES可以直接获取到
function convertBase64UrlToBlob(urlData) {
var arr = urlData.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 Blob([u8arr], {
type: mime
});
}
上传部分
$('.sub').unbind('click').on('click',function(){
// alert(3);
console.log(Date.parse(new Date()));
file = convertBase64UrlToBlob($(".img").attr('src'));
var base64img = $(".img").attr('src');
var formData = new FormData();
// formData.append("image2", base64img, "file64_" + Date.parse(new Date()) + ".jpg");
formData.append("image", file, "file_" + Date.parse(new Date()) + ".jpg");
$.ajax({
url: '{:url("Index/upfile")}',
type: 'POST',
dataType: 'JSON',
data: formData,
// data: {'image2':base64img},
// 告诉jQuery不要去处理发送的数据
processData: false,
// 告诉jQuery不要去设置Content-Type请求头
contentType: false,
})
.done(function(e) {
console.log(Date.parse(new Date()));
console.log(e);
})
.fail(function() {
console.log("error");
})
.always(function() {
console.log("complete");
});
})
后台部分
public function upfile()
{
// $file = request()->file('image');
$file = input('file.image');
$file2 = input('image2');
if($file2){
// $file = input('sharepic'); //base64de
// if (!$file) return $this->_A(false, '图片不存在');
$str = $file2; //获取上传文件字符串
$str = str_replace(' ', '+', $str); //替换空字符串为+
$str = str_replace('\n', '', $str); //置空换行符
$str = str_replace('\t', '', $str);
$str = str_replace('\r', '', $str);
$str = explode(',', $str);
$str = stripslashes($str[1]); //过虑转义符
$img = base64_decode($str); //解码
$path = ROOT_PATH . 'public' . DS . 'uploads' . DS . date('Ymd');
@mkdir($path, 0755, true);
$filename = '/uploads/'.date('Ymd').'/'.time().rand(100000,999999).'.png';
if(file_put_contents('.'.$filename, $img)){
return json(['status' => 1, 'msg' => 'ok', 'path' => $filename]);
}else{
$this->_A(false,'操作失败,请稍后再试');
}
}
if ($file) {
$info = $file->move(ROOT_PATH . 'public' . DS . 'uploads');
if ($info) {
// 成功上传后 获取上传信息
$path = 'uploads' . DS . $info->getSaveName();
// $model = db('img');
// $model->insert(['user_id' => $this->user_id, 'img' => $path, 'create_time' => time()]);
$path = DS . $path;
// $image = \think\Image::open('.'.$path);
// $image->thumb(500,500)->save($path);
return json(['status' => 1, 'msg' => 'ok', 'path' => $path]);
} else {
// 上传失败获取错误信息
// $file->getError();
return json(['status' => 0, 'msg' => '图片上传失败']);
}
} else {
return json(['status' => 0, 'msg' => '请选择上传文件']);
}
}
经测试 这种方式比上传base64图片快3倍,并减少后台服务器压力,
需要引用的js:jquery-3.2.1.min.js exif.js
后台语言PHP 框架thinkphp5
用到的js
点击打开链接
版权声明:本文为yaofare原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。