将图像读入JS以便随后压缩它

时间:2018-01-30 01:09:01

标签: javascript

我是前端开发新手的服务器端开发人员。我一直在修补vanilla Javascript,需要澄清一些概念。

我正在尝试的用例是通过JS处理图像上传(以及在上传到服务器之前的半空中JS辅助压缩)。

目前我坚持第一步。想象一下以下简单的设置:

__mocks__/

我的问题是:

我在什么步骤尝试将图像传递给JS函数(鉴于我的目标是压缩它并将其发送到服务器)?这会在图像选择时发生(即按下<form method="POST" action="some_url"> <input type="file" id="browse_image" onchange="compressImage(event)"> <input type="submit" value="Submit"> </form> 按钮),还是按下browse?我在哪里举办活动,如何从那里开始?一个例子的快速说明性答案将是伟大的!

我一直试图在图像选择时做到这一点(无济于事):

Submit

获得概念性演练以及快速说明性示例会很棒。仅限Vanilla JS,在我掌握JS之前,我不会触及JQuery。

1 个答案:

答案 0 :(得分:1)

在我看来(但它有点主观),你会在两个地方都这样做。

  1. 用户从您的输入中选择文件
  2. 您通过js
  3. 处理文件
  4. 如果处理失败(例如文件不是图像/损坏/谁知道),您可以直接告诉用户。
  5. 如果处理成功,当用户点击提交时,您将覆盖表单的默认行为,并发送包含新文件/ Blob的FormData而不是原始文件/ Blob。< / LI>

    &#13;
    &#13;
    var toSend = null, // here we will store our processed File/Blob (the one to send)
    browse_image = document.getElementById('browse_image');
    
    // when user selects a new File
    browse_image.onchange = process_user_file;
    // when user decides to send it to server
    document.querySelector('form').onsubmit = overwrite_default_submit;
    
    // grab the file from the input and process it
    function process_user_file(evt) {
      // since we attached the event listener through elem.onevent,
      // 'this' refers to the input
      var file = this.files[0];
      // here do your compression, for demo, we'll just check it's a png file
      var reader = new FileReader();
      // a FileReader is async, so we pass the actual checking script as the onload handler
      reader.onload = checkMagicNumber;
      reader.readAsArrayBuffer(file.slice(0,4));
    }
    
    // we don't want the real form to be submitted, but our processed File/Blob
    function overwrite_default_submit(evt) {
      // block the form's submit default behavior
      evt.preventDefault();
      // create a new form result from scratch
      var form = new FormData();
      // add our File/Blob
      form.append("myfile", toSend, browse_image.files[0].name);
      // create a new AJAX request that will do the same as original form's behavior
      var xhr = new XMLHttpRequest();
      xhr.open('POST', evt.target.action);
    //  xhr.send(form); // uncomment to really send the request
      console.log('sent', toSend);
    }
    
    // simply checks if it's really a png file
    // for you, it will be your own compression code,
    //  which implementation can not be discussed in this answer
    function checkMagicNumber(evt) {
      var PNG = '89504e47';
      var arr = new Uint8Array(evt.target.result);
      var header = "";
      for(var i = 0; i < arr.length; i++) {
         header += arr[i].toString(16);
      }
      // some user friendly actions
      if(header !== PNG) {
        alert('not a png file'); // let the user know it didn't work
        browse_image.value = ""; // remove invalid File
        sub.disabled = true; // avoid the form's submission
        toSend = null; // nothing to send
      }
      else {
        toSend = browse_image.files[0]; // for demo we don't actually modify it...
        sub.disabled = false; // allow form's submission
      }
    }
    &#13;
    <form method="POST" action="some_url">
      <label>Please select a .png file</label>
      <input type="file" id="browse_image" name="myfile">
      <input type="submit" value="Submit" disabled id="sub">
    </form>
    &#13;
    &#13;
    &#13;

    Ps:请注意,即使您的原始代码也没有发送任何内容,因为表单中的输入中没有name属性。