Angular 9: как преобразовать формат файла HEIF в известный веб-формат при загрузке изображений

Я поддерживаю веб-приложение (PWA), написанное на Angular 9, где пользователи загружают изображения и обрезают, поворачивают и т. Д. В Cropperjs.

В iOS новый формат изображений (HEIF) становится стандартом, и эти пользователи жалуются, что не могут загрузить свои фотографии. Кажется, что иногда iOS автоматически конвертирует в jpg, а иногда нет. Поэтому нам нужно иметь возможность получать изображения в формате HEIF.

Я попытался добавить изображение/heif mimetype к атрибуту accept, но изображения *.heic по-прежнему затемнены на iOS. Мне кажется, что многие просто принимают все файлы, но это не вариант для этого веб-приложения.

Кроме того, Cropperjs не поддерживает формат изображения HEIF, так как же нам преобразовать его в известный веб-формат?


person Jette    schedule 05.11.2020    source источник


Ответы (2)


Решение для нас состояло в том, чтобы установить heic2any:

npm install heic2any

Затем импортируйте его в компонент, где он нужен:

import heic2any from "heic2any";

В атрибуте accept добавьте mimetype и расширение файла.

image/jpeg, image/png, image/heif, .heic, .heif

И если вам нужно поддерживать загрузку любого изображения:

image/*, .heic, .heif

Мы используем ngfSelect, и это выглядит так (упрощенно):

<div ngfSelect
  [accept]  = "'image/*, .heic, .heif'"
  (filesChange) = "imageSelected($event)">
  

Ниже приведена упрощенная версия функции imageSelected().

public imageSelected(event) {
  let f:File;

  //RECEIVE IMAGE

  if (event[0] && (event[0]['lastModified'] || event[0]['lastModifiedDate'])) {
    f = event[0];
    if (event.length > 1) {
      event.splice(0,event.length-1);
      f = event[0];
    }
  } else if (event.target && event.target.files && event.target.files[0]) {
    f = event.target.files[0];
  }

  if (!f) {
    //Handle error and exit
  }

  let blob:Blob = f;
  let file:File = f;

  let convProm:Promise<any>;
  
  //CONVERT HEIC TO JPG

  if (/image\/hei(c|f)/.test(f.type)) {
    convProm = heic2any({blob,toType:"image/jpeg",quality:0}).then((jpgBlob:Blob) => {

      //Change the name of the file according to the new format
      let newName = f.name.replace(/\.[^/.]+$/, ".jpg");

      //Convert blob back to file
      file = this.blobToFile(jpgBlob,newName);

    }).catch(err => {
      //Handle error
    });
  } else {
    //This is not a HEIC image so we can just resolve
    convProm = Promise.resolve(true);
  }

  //ADD IMAGE FILE TO CROPPERJS EDITOR

  convProm.then(() => {
    
    let reader = new FileReader();
    let _thisComp = this;

    //Add file to FileReader
    if (file) {
      reader.readAsDataURL(file);
    }
    //Listen for FileReader to get ready
    reader.onload = function () {
      
      //Set imageUrl. This will trigger initialization of cropper via imageLoaded() 
      //as configured in the html img tag:
      //<img #image id="image" [src]="imageUrl" (load)="imageLoaded($event)" class="cropper"> 

      _thisComp.imageUrl = reader.result;
    }
  });
}


private blobToFile = (theBlob: Blob, fileName:string): File => {
  let b: any = theBlob;

  //A Blob() is almost a File() - it's just missing the two properties below which we will add
  b.lastModified = new Date();
  b.name = fileName;

  //Cast to a File() type
  return <File>theBlob;
}

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

person Jette    schedule 05.11.2020

heic2any работает ТОЛЬКО на стороне клиента; это означает, что если вы используете heic2any; вы, возможно, сломаете угловую сборку - предварительный рендеринг и столкнетесь с проблемой обновления маршрута.

person Fatih Kurnaz    schedule 22.04.2021
comment
На данный момент это работает нормально, но я знаю, что heic2any потенциально может создать нам проблемы в будущем. Я искал плагин для Angular, который делает то же самое, но, к сожалению, не нашел. - person Jette; 03.05.2021
comment
К сожалению, формат HEIC действительно вызывает головную боль, и некоторые браузеры не поддерживают его полностью. Поэтому; пакеты не могут обеспечить идеальное решение для этого на данный момент - person Fatih Kurnaz; 14.05.2021