Angular 9:上传图像时如何将 HEIF 文件格式转换为已知的 Web 格式

2024-05-14

我正在维护一个用 Angular 9 编写的 Web 应用程序(PWA),用户可以在 Cropperjs 中上传图像并裁剪、旋转等。

在 iOS 上,新的图像格式 (HEIF) 正在成为标准,这些用​​户抱怨他们无法上传照片。似乎iOS有时会自动转换为jpg,有时则不会。因此我们需要能够接收 HEIF 格式的图像。

我尝试将 mimetype image/heif 添加到accept属性,但 *.heic 图像在 iOS 上仍然呈灰色。我似乎很多人只是选择接受所有文件,但这不是这个网络应用程序的选项。

而且cropperjs不支持HEIF图像格式,那么我们如何转换为已知的Web格式呢?


我们的解决方案是安装heic2any https://github.com/alexcorvi/heic2any:

npm install heic2any

然后将其导入到需要的组件中:

import heic2any from "heic2any";

In the 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;
}

以上可能不是最漂亮的解决方案,但我希望它能为面临同样挑战的其他人提供帮助和启发。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Angular 9:上传图像时如何将 HEIF 文件格式转换为已知的 Web 格式 的相关文章

随机推荐