我需要一个解决方案,用于在使用XMLHttpRequest或ajax上传之前使用正确的EXIF方向预览图像。我已经能够预览图像并在iPhone上更正方向或通过XMLHttpRequest提交,但不能同时提交。
请随意提出其他解决方案:
允许用户使用iPhone / Android以正确的方向预览图像并在上传之前提取图像的EXIF信息
我正在使用Fengyuan Chen's exif.js,代码如下:
HTML
<form action="upload.php" id="form" method="POST" enctype="multipart/form-data">
<div class="docs-preview docs-dropzone">
<input id="upload" type="file" name="file" accept="image/*" />
<label for="upload">
<div id="image-preview"><img src="../_images/upload.svg"></div>
</label>
<button id='btn'>Upload</button>
</div>
</form>
<script src="jquery-2.2.4.min.js"></script>
<script src="1.9.2/jquery-ui.min.js"></script>
<script src="exif.js"></script>
<script src="main.js"></script>
main.js
const ORIENT_TRANSFORMS = {
1: '',
2: 'rotateY(180deg)',
3: 'rotate(180deg)',
4: 'rotate(180deg) rotateY(180deg)',
5: 'rotate(270deg) rotateY(180deg)',
6: 'rotate(90deg)',
7: 'rotate(90deg) rotateY(180deg)',
8: 'rotate(270deg)'
}
function getOrientation( file ) {
return new Promise( ( resolve, reject ) => {
const reader = new FileReader();
reader.onerror = reject
reader.onload = ( { target } ) => {
try {
const view = new DataView( target.result ),
length = view.byteLength
let offset = 2
if( view.getUint16(0, false) != 0xFFD8 ) {
return reject( new Error( 'File is not a .jpeg' ) )
}
while( offset < length ) {
const marker = view.getUint16( offset, false )
offset += 2;
if (marker == 0xFFE1) {
if( view.getUint32( offset += 2, false ) != 0x45786966 ) {
return resolve()
}
const little = view.getUint16(offset += 6, false) == 0x4949
offset += view.getUint32(offset + 4, little)
const tags = view.getUint16(offset, little)
offset += 2
for( var i = 0; i < tags; i++ ) {
if( view.getUint16( offset + ( i * 12 ), little ) == 0x0112 ) {
return resolve( view.getUint16( offset + ( i * 12 ) + 8, little ) )
}
}
} else if( ( marker & 0xFF00 ) != 0xFF00 ) {
break;
} else {
offset += view.getUint16( offset, false )
}
}
return resolve()
} catch( err ) {
return reject( err )
}
};
reader.readAsArrayBuffer( file.slice( 0, 64 * 1024 ) );
} )
}
window.onload = function () {
'use strict';
var Exif = window.Exif;
var URL = window.URL || window.webkitURL;
var preview = document.getElementsByClassName('docs-preview')[0];
var dropzone = document.getElementsByClassName('docs-dropzone')[0];
var fileInput = dropzone.getElementsByTagName('input')[0];
var options = {
done: function (tags) {
var segments = [];
var tag;
for (tag in tags) {
if (tags.hasOwnProperty(tag)) {
if (tag == 'Orientation') {
var orientation = tags[tag];
console.log(+orientation);
img.style.transform = ORIENT_TRANSFORMS[ getOrientation(fileInput) ];
}
}
}
},
fail: function (message) {
console.log(message);
}
};
function readExif() {
return new Exif(preview.getElementsByTagName('img')[0], options);
}
function readExifFromFile(file) {
var image;
if (file.type === 'image/jpeg') {
if (URL) {
image = new Image();
image.onload = function () {
this.onload = null;
URL.revokeObjectURL(file);
};
image.src = URL.createObjectURL(file);
// Clear existing image
preview.innerHTML = '';
preview.appendChild(image);
}
// Clear chosen file
fileInput.value = '';
return new Exif(file, options);
} else {
window.alert('Por favor envie uma imagem JPEG.');
}
}
readExif();
fileInput.onchange = function (e) {
var files = e.target.files;
if (files && files.length) {
readExifFromFile(files[0]);
}
};
dropzone.ondragover = function (e) {
e.preventDefault();
};
dropzone.ondrop = function (e) {
var files = e.dataTransfer.files;
e.preventDefault();
if (files && files.length) {
readExifFromFile(files[0]);
}
};
};
var $formUpload = document.getElementById('form'),
$preview = document.getElementById('btn'),
i = 0;
$formUpload.addEventListener('submit', function(event){
event.preventDefault();
var xhr = new XMLHttpRequest();
xhr.open("POST", $formUpload.getAttribute('action'));
var formData = new FormData($formUpload);
formData.append("i", i++);
xhr.send(formData);
xhr.addEventListener('readystatechange', function() {
if (xhr.readyState === 4 && xhr.status == 200) {
var json = JSON.parse(xhr.responseText);
if (!json.error && json.status === 'ok') {
$preview.innerHTML += 'File sent!';
} else {
$preview.innerHTML = 'File not sent';
console.log(json.error);
}
} else {
$preview.innerHTML = xhr.statusText;
}
});
xhr.upload.addEventListener("progress", function(e) {
if (e.lengthComputable) {
var percentage = Math.round((e.loaded * 100) / e.total);
$preview.innerHTML = String(percentage) + '%';
}
}, false);
xhr.upload.addEventListener("load", function(e){
$preview.innerHTML = String(100) + '%';
}, false);
}, false);
upload.php的
<?php
date_default_timezone_set('America/Sao_Paulo');
$dir = 'upload/';
$today = date('Y-m-d');
if (isset($_FILES['file'])) {
$name = $_FILES['file']['name'];
$tmp_name = $_FILES['file']['tmp_name'];
$path = $_FILES['file']['name'];
$extension = pathinfo($path, PATHINFO_EXTENSION);
if ($extension == 'jpeg') {
$ext = '.jpg';
} else {
$ext = strtolower(substr($_FILES['file']['name'],-4));
}
$new_name = $today."_"."01".$ext;
$error = $_FILES['file']['error'];
if ($error !== UPLOAD_ERR_OK) {
$ret = 'Upload error:'. $error;
} elseif (move_uploaded_file($tmp_name, $dir . $new_name)) {
$ret = array('status' => 'ok');
}
} else {
header('Content-Type: application/json');
$ret = array('error' => 'no_file');
echo json_encode($ret);
exit;
} ?>
我可以在iPhone上正确预览图像,但在控制台上收到消息“no_file”。或者我可以在禁用EXIF预览时上传文件。
有什么想法吗?提前谢谢!