Angular9:上传图片时如何将HEIF文件格式转换为已知的网页格式
Angular 9: How to convert HEIF file format to a known web format when uploading images
我正在维护一个用 Angular 9 编写的网络应用程序 (PWA),用户可以在其中上传图像并在 cropperjs 中裁剪、旋转等。
在 iOS 上,一种新的图像格式 (HEIF) 正在成为标准,这些用户抱怨他们无法上传他们的照片。好像有时候iOS会自动转成jpg,有时候不会。因此我们需要能够接收HEIF格式的图片。
我尝试将 mimetype image/heif 添加到 accept
属性,但 *.heic 图像在 iOS 上仍然变暗。我似乎很多人只是选择接受所有文件,但这不是这个网络应用程序的选项。
另外cropperjs不支持HEIF图片格式,那么如何转换成已知的网页格式呢?
我们的解决方案是安装 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;
}
以上可能不是最完美的解决方案,但希望能对面临同样挑战的其他人有所帮助和启发。
heic2any 仅适用于客户端;这意味着如果你使用 heic2any;您可能会破坏 angular 构建 - 预渲染并且您将面临刷新路由问题。
我正在维护一个用 Angular 9 编写的网络应用程序 (PWA),用户可以在其中上传图像并在 cropperjs 中裁剪、旋转等。
在 iOS 上,一种新的图像格式 (HEIF) 正在成为标准,这些用户抱怨他们无法上传他们的照片。好像有时候iOS会自动转成jpg,有时候不会。因此我们需要能够接收HEIF格式的图片。
我尝试将 mimetype image/heif 添加到 accept
属性,但 *.heic 图像在 iOS 上仍然变暗。我似乎很多人只是选择接受所有文件,但这不是这个网络应用程序的选项。
另外cropperjs不支持HEIF图片格式,那么如何转换成已知的网页格式呢?
我们的解决方案是安装 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;
}
以上可能不是最完美的解决方案,但希望能对面临同样挑战的其他人有所帮助和启发。
heic2any 仅适用于客户端;这意味着如果你使用 heic2any;您可能会破坏 angular 构建 - 预渲染并且您将面临刷新路由问题。