在上载之前在客户端调整图像大小

时间:2018-04-10 17:10:07

标签: javascript php jquery html5

是否有任何客户端脚本可以自动调整用户在输入文件中上传的图像的大小,并通过在同一输入中调整大小的新图像自动替换旧图像..我想这样做以将此图像发送到我的PHP模型之后..先感谢您的帮助。

 <!DOCTYPE HTML>
 <html>
 <head>
     <title>Untitled</title>
 </head>
 <body>
    <form action="model.php" method="post" enctype="multipart/form-data">
       <input type="file" name="image"/>
       <input type="submit" name="do" value="submit"/>
    </form>
 </body>
 </html>

<?php
$target_dir = "folder/";
$filename    = $_FILES["image"]["name"];
$basename    = basename($_FILES["image"]["name"]);
$target_file = $target_dir .$basename;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
$tmp         = $_FILES["image"]["tmp_name"];
if(move_uploaded_file($tmp,$target_file))
{
    echo'done!';
}
?>

2 个答案:

答案 0 :(得分:2)

您可以通过FileReader API将图像绘制到调整大小的画布,然后使用canvas.toDataURL('image/png')将base64图像发送到服务器。

以下是将图像大小调整为320x240的简化示例:

document.getElementById('example').addEventListener('change', function(e) {


	var canvas = document.createElement('canvas')
	var canvasContext = canvas.getContext('2d')
	canvas.setAttribute("style", 'opacity:0;position:absolute;z-index:-1;top: -100000000;left:-1000000000;width:320px;height:240px;')
  document.body.appendChild(canvas);
  
  var img = new Image;
  img.onload = function() {
      canvasContext.drawImage(img, 0, 0, 320, 240);
    	var base64Image = canvas.toDataURL('image/png')
      console.log(base64Image)
      // Post to server
      // sendImage(base64Image)
      
      document.body.removeChild(canvas)
    	URL.revokeObjectURL(img.src)
  }
	img.src = URL.createObjectURL(e.target.files[0]);
})

function sendImage() {
    var data = canvas.toDataURL('image/png');
    var ajax = null;
    if (window.XMLHttpRequest) {
        ajax = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        ajax = new ActiveXObject("Microsoft.XMLHTTP");
    }

    ajax.open('POST', 'https://example/route', true);
    ajax.setRequestHeader('Content-Type', 'application/octet-stream');
    ajax.onreadystatechange = function() {
        if (ajax.readyState === XMLHttpRequest.DONE) {
            if (ajax.status === 200) {
                // Success
            } else {
                // Fail
            }
        }
    };

    ajax.send(data);
}
<input id="example" type="file" />

然后在服务器上:

// or however you want to get the posted contents.
$png = isset($GLOBALS["HTTP_RAW_POST_DATA"]) ? $GLOBALS["HTTP_RAW_POST_DATA"] : file_get_contents("php://input");
if (strpos($png, 'data:image/png;base64,') === 0) {
$png = str_replace('data:image/png;base64,', '', $png);
$png = str_replace(' ', '+', $png);
$png = base64_decode($png);
}

file_put_contents($image_path, $png);

修改
该代码现在包括将图像上传到服务器的方法 您还可以使用 jQuery 或更现代的fetch API来上传图像。 JsFiddle available here

答案 1 :(得分:2)

这就是我如何解决它......

// Used for creating a new FileList in a round-about way
function FileListItem(a) {
  a = [].slice.call(Array.isArray(a) ? a : arguments)
  for (var c, b = c = a.length, d = !0; b-- && d;) d = a[b] instanceof File
  if (!d) throw new TypeError("expected argument to FileList is File or array of File objects")
  for (b = (new ClipboardEvent("")).clipboardData || new DataTransfer; c--;) b.items.add(a[c])
  return b.files
}

fileInput.onchange = function change() {
  const file = this.files[0]
  if (!file) return

  
  file.image().then(img => {
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    const maxWidth = 320
    const maxHeight = 240

    // calculate new size
    const ratio = Math.min(maxWidth / img.width, maxHeight / img.height)
    const width = img.width * ratio + .5 | 0
    const height = img.height * ratio + .5 | 0

    // resize the canvas to the new dimensions
    canvas.width = width
    canvas.height = height

    // scale & draw the image onto the canvas
    ctx.drawImage(img, 0, 0, width, height)
    
    // just to preview
    // document.body.appendChild(canvas)

    // Get the binary (aka blob)
    canvas.toBlob(blob => {
      const resizedFile = new File([blob], file.name, file)
      const fileList = new FileListItem(resizedFile)

      // temporary remove event listener since
      // assigning a new filelist to the input
      // will trigger a new change event...
      fileInput.onchange = null
      fileInput.files = fileList
      fileInput.onchange = change
    })
  })
}
<!-- screw-filereader will take care of exif rotation for u -->
<script src="https://cdn.jsdelivr.net/npm/screw-filereader@1.4.3/index.min.js"></script>

<form action="https://httpbin.org/post" method="post" enctype="multipart/form-data">
  <input type="file" id="fileInput" name="image" accept="image/*" />
  <input type="submit" name="do" value="submit" />
</form>

PS。由于iframe更加沙盒化和安全,它不会在stackoverflow中调整大小,在jsfiddle中工作:https://jsfiddle.net/f2oungs3/3/