Можно ли создать миниатюру с помощью FileReader API? - PullRequest
0 голосов
/ 18 сентября 2018

У меня есть подтверждение концепции, которая необходима для загрузки нескольких изображений с помощью FileReader.readAsDataURL () .

Однако рабочий процесс моих клиентов таков, что они загружаютсяв сотнях изображений одновременно, что приводит к сбою браузера.

Есть ли способ загрузить эти изображения в виде реальных миниатюр (16 КБ против 16 МБ)?

1 Ответ

0 голосов
/ 18 сентября 2018

Во-первых, вообще не используйте FileReader.

Вместо этого для отображения любых данных из BLOB-объекта используйте метод URL.createObjectURL.
FileReader будет загружать двоичные данные трижды в память (один при чтении BLOB-объекта для преобразования, один как Base64 String и один при передаче как источник вашего HTMLElement.)
В случае файла, сохраненного на пользовательском диске, blobURL загрузит данные только один раз в память из HTMLElement. BlobURL действительно является прямым указателем на данные BLOB-объекта.

Так что это уже освободит вам много памяти.

inp.onchange = e => {
  for(let file of inp.files) {
    let url = URL.createObjectURL(file);
    let img = new Image(200);
    img.src = url;
    document.body.appendChild(img);
  }
};
    
<input type="file" webkitdirectory accepts="image/*" id="inp">

Теперь, если этого недостаточно, для создания миниатюр вы можете нарисовать все эти изображения на холстах и ​​при необходимости уменьшить их размер. Но имейте в виду, что для этого вам все равно придется сначала загрузить данные исходного изображения, и вы не можете быть уверены, как браузер очистит эту использованную память. Так что, создавая эти версии миниатюр, может принести больше вреда, чем что-либо другое.

В любом случае, вот основной пример того, как это может быть реализовано:

inp.onchange = e => {
  Promise.all([...inp.files].map(toThumbnail))
    .then(imgs => document.body.append.apply(document.body, imgs.filter(v => v)))
    .catch(console.error);
};

function toThumbnail(file) {
  return loadImage(file)
    .then(drawToCanvas)
    .catch(_ => {});
}

function loadImage(file) {
  const url = URL.createObjectURL(file);
  const img = new Image();
  return new Promise((res, rej) => {
    img.onload = e => res(img);
    img.onerror = rej;
    img.src = url;
  });
};

function drawToCanvas(img) {
  const w = Math.min(img.naturalWidth, 200);
  const r = w / img.naturalWidth;
  const h = img.naturalHeight * r;
  const canvas = Object.assign(
    document.createElement('canvas'), {
      width: w,
      height: h
    }
  );
  canvas.getContext('2d').drawImage(img, 0, 0, w, h);
  return canvas;
}
<input type="file" webkitdirectory accepts="image/*" id="inp">
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...