Handle files with an heic extension that are not actually heic
This commit is contained in:
parent
d110645703
commit
3dae87abaa
4 changed files with 27 additions and 13 deletions
|
@ -9,6 +9,9 @@ import FileType from "file-type";
|
|||
*
|
||||
* It first peeks into the file's initial contents to detect the MIME type. If
|
||||
* that doesn't give any results, it tries to deduce it from the file's name.
|
||||
*
|
||||
* For the list of returned extensions, see (for our installed version):
|
||||
* https://github.com/sindresorhus/file-type/blob/main/core.d.ts
|
||||
*/
|
||||
export const detectMediaMIMEType = async (file: File): Promise<string> => {
|
||||
const chunkSizeForTypeDetection = 4100;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { FILE_TYPE } from "@/media/file-type";
|
||||
import { isNonWebImageFileExtension } from "@/media/formats";
|
||||
import { isHEICExtension, isNonWebImageFileExtension } from "@/media/formats";
|
||||
import { scaledImageDimensions } from "@/media/image";
|
||||
import { decodeLivePhoto } from "@/media/live-photo";
|
||||
import { createHEICConvertComlinkWorker } from "@/media/worker/heic-convert";
|
||||
|
@ -285,10 +285,14 @@ const isFileEligible = (file: EnteFile) => {
|
|||
if (!isImageOrLivePhoto(file)) return false;
|
||||
if (file.info.fileSize > 100 * 1024 * 1024) return false;
|
||||
|
||||
// This check is fast but potentially incorrect because in practice we do
|
||||
// encounter files that are incorrectly named and have a misleading
|
||||
// extension. To detect the actual type, we need to sniff the MIME type, but
|
||||
// that requires downloading and decrypting the file first.
|
||||
const [, extension] = nameAndExtension(file.metadata.title);
|
||||
if (isNonWebImageFileExtension(extension)) {
|
||||
// Of the known non-web types, we support HEIC.
|
||||
return isHEIC(extension);
|
||||
return isHEICExtension(extension);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -299,11 +303,6 @@ const isImageOrLivePhoto = (file: EnteFile) => {
|
|||
return fileType == FILE_TYPE.IMAGE || fileType == FILE_TYPE.LIVE_PHOTO;
|
||||
};
|
||||
|
||||
const isHEIC = (extension: string) => {
|
||||
const ext = extension.toLowerCase();
|
||||
return ext == "heic" || ext == "heif";
|
||||
};
|
||||
|
||||
export const heicToJPEG = async (heicBlob: Blob) => {
|
||||
let worker = heicWorker;
|
||||
if (!worker) heicWorker = worker = createHEICConvertComlinkWorker();
|
||||
|
@ -336,14 +335,17 @@ const renderableImageBlob = async (castToken: string, file: EnteFile) => {
|
|||
blob = new Blob([imageData]);
|
||||
}
|
||||
|
||||
const [, ext] = nameAndExtension(fileName);
|
||||
if (isHEIC(ext)) {
|
||||
blob = await heicToJPEG(blob);
|
||||
}
|
||||
|
||||
// We cannot rely on the file's extension to detect the file type, some
|
||||
// files are incorrectly named. So use a MIME type sniffer first, but if
|
||||
// that fails than fallback to the extension.
|
||||
const mimeType = await detectMediaMIMEType(new File([blob], fileName));
|
||||
if (!mimeType)
|
||||
throw new Error(`Could not detect MIME type for file ${fileName}`);
|
||||
|
||||
if (mimeType == "image/heif" || mimeType == "image/heic") {
|
||||
blob = await heicToJPEG(blob);
|
||||
}
|
||||
|
||||
return new Blob([blob], { type: mimeType });
|
||||
};
|
||||
|
||||
|
|
|
@ -5,10 +5,11 @@ import { lowercaseExtension } from "@/next/file";
|
|||
import log from "@/next/log";
|
||||
import { CustomErrorMessage, type Electron } from "@/next/types/ipc";
|
||||
import { workerBridge } from "@/next/worker/worker-bridge";
|
||||
import { withTimeout } from "@/utils/promise";
|
||||
import ComlinkCryptoWorker from "@ente/shared/crypto";
|
||||
import { LS_KEYS, getData } from "@ente/shared/storage/localStorage";
|
||||
import { User } from "@ente/shared/user/types";
|
||||
import { downloadUsingAnchor, withTimeout } from "@ente/shared/utils";
|
||||
import { downloadUsingAnchor } from "@ente/shared/utils";
|
||||
import { t } from "i18next";
|
||||
import isElectron from "is-electron";
|
||||
import { moveToHiddenCollection } from "services/collectionService";
|
||||
|
|
|
@ -24,3 +24,11 @@ const nonWebImageFileExtensions = [
|
|||
*/
|
||||
export const isNonWebImageFileExtension = (extension: string) =>
|
||||
nonWebImageFileExtensions.includes(extension.toLowerCase());
|
||||
|
||||
/**
|
||||
* Return `true` if {@link extension} in for an HEIC-like file.
|
||||
*/
|
||||
export const isHEICExtension = (extension: string) => {
|
||||
const ext = extension.toLowerCase();
|
||||
return ext == "heic" || ext == "heif";
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue