Вывод toDataURL - base64, как уменьшить время загрузки и пропускную способность в 1/3? - PullRequest
0 голосов
/ 01 июля 2018

Цель следующего кода - сжать входной файл (JPG-файл 2 МБ => 500 КБ файл), а затем загрузить его на сервер при отправке <form>.

При импорте изображения из файла JPG на холст и его экспорте с помощью toDataURL с помощью:

function doit() {
    var file = document.getElementById('file').files[0],
        canvas = document.getElementById('canvas'),
        hidden = document.getElementById('hidden'),
        ctx = canvas.getContext("2d"),
        img = document.createElement("img"),
        reader = new FileReader();  
    
    reader.onload = function(e) { 
        img.src = e.target.result;
    }
    
    img.onload = function () { 
        ctx.drawImage(img, 0, 0);
        hidden.value = canvas.toDataURL("image/jpeg", 0.5);
    }
    reader.readAsDataURL(file);
}
<input type="file" onchange="doit();" id="file" />

<form action="/upload" method="post">
<input type="hidden" id="hidden" />
<input type="submit" />
</form>

<canvas id="canvas" style="display: none" />

это работает, но поле hidden вывода в <form> закодировано в base64, то есть что-то вроде:

data:image/jpeg;base64,/9j/4AAQSkZJRgAB...

Хорошо известно, что base64 использует в 1,3333 раза больше нормального размера двоичных данных.

Вопрос: как в этом случае не тратить 1/3 данных на время загрузки (клиент => сервер) и пропускную способность, т. Е. При отправке <form>?

Примечание: я думаю, что проблема будет той же, если я использую AJAX вместо <form> представления, не так ли?

1 Ответ

0 голосов
/ 01 июля 2018

var jsForm = null;

function doit() {
    var file = document.getElementById('file').files[0],
        canvas = document.getElementById('canvas'),
        ctx = canvas.getContext("2d"),
        img = document.createElement("img");

    img.src = window.URL.createObjectURL(file);
    
    img.onload = function () {
        if (!jsForm) {
          jsForm = new FormData();
        }
        ctx.drawImage(img, 0, 0);
        canvas.toBlob(function(blob) {
          jsForm.set('image', blob, file.name);
        }, "image/jpeg", 0.5);
    }
}

var form = document.getElementById('form');
form.onsubmit = function(e) {
  e.preventDefault();
  if (!jsForm) return;
  var request = new XMLHttpRequest();
  request.open(this.method||'POST', this.action||'/');
  request.send(jsForm);
  jsForm = null;
}
<form method="POST" action ="/upload" id="form">
  <input type="file" onchange="doit();" id="file" />
  <button>Submit</button>
</form>
<canvas id="canvas" style="display: none" />
...