具有EXIF方向预览的XMLHttpRequest图像上传器

时间:2017-08-11 15:30:01

标签: javascript upload xmlhttprequest orientation exif

我需要一个解决方案,用于在使用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预览时上传文件。

有什么想法吗?提前谢谢!

0 个答案:

没有答案