Merge pull request #557 from ente-io/array-buffer

Move to using arrayBuffer instead of readAsArrayBuffer
This commit is contained in:
Abhinav Kumar 2022-05-23 18:27:48 +05:30 committed by GitHub
commit 9a4e7f946d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 112 additions and 161 deletions

View file

@ -4,7 +4,6 @@ import { parseFFmpegExtractedMetadata } from 'utils/ffmpeg';
class FFmpegClient { class FFmpegClient {
private ffmpeg: FFmpeg; private ffmpeg: FFmpeg;
private fileReader: FileReader;
private ready: Promise<void> = null; private ready: Promise<void> = null;
constructor() { constructor() {
this.ffmpeg = createFFmpeg({ this.ffmpeg = createFFmpeg({
@ -19,9 +18,6 @@ class FFmpegClient {
if (!this.ffmpeg.isLoaded()) { if (!this.ffmpeg.isLoaded()) {
await this.ffmpeg.load(); await this.ffmpeg.load();
} }
if (!this.fileReader) {
this.fileReader = new FileReader();
}
} }
async generateThumbnail(file: File) { async generateThumbnail(file: File) {
@ -31,7 +27,7 @@ class FFmpegClient {
this.ffmpeg.FS( this.ffmpeg.FS(
'writeFile', 'writeFile',
inputFileName, inputFileName,
await getUint8ArrayView(this.fileReader, file) await getUint8ArrayView(file)
); );
let seekTime = 1.0; let seekTime = 1.0;
let thumb = null; let thumb = null;
@ -66,7 +62,7 @@ class FFmpegClient {
this.ffmpeg.FS( this.ffmpeg.FS(
'writeFile', 'writeFile',
inputFileName, inputFileName,
await getUint8ArrayView(this.fileReader, file) await getUint8ArrayView(file)
); );
let metadata = null; let metadata = null;

View file

@ -1,10 +1,11 @@
import * as HeicConvert from 'heic-convert'; import * as HeicConvert from 'heic-convert';
import { getUint8ArrayView } from 'services/readerService';
export async function convertHEIC( export async function convertHEIC(
fileBlob: Blob, fileBlob: Blob,
format: string format: string
): Promise<Blob> { ): Promise<Blob> {
const filedata = new Uint8Array(await fileBlob.arrayBuffer()); const filedata = await getUint8ArrayView(fileBlob);
const result = await HeicConvert({ buffer: filedata, format }); const result = await HeicConvert({ buffer: filedata, format });
const convertedFileData = new Uint8Array(result); const convertedFileData = new Uint8Array(result);
const convertedFileBlob = new Blob([convertedFileData]); const convertedFileBlob = new Blob([convertedFileData]);

View file

@ -44,7 +44,6 @@ export async function replaceThumbnail(
try { try {
const token = getToken(); const token = getToken();
const worker = await new CryptoWorker(); const worker = await new CryptoWorker();
const reader = new FileReader();
const files = await getLocalFiles(); const files = await getLocalFiles();
const trash = await getLocalTrash(); const trash = await getLocalTrash();
const trashFiles = getTrashedFiles(trash); const trashFiles = getTrashedFiles(trash);
@ -77,9 +76,8 @@ export async function replaceThumbnail(
[originalThumbnail], [originalThumbnail],
file.metadata.title file.metadata.title
); );
const fileTypeInfo = await getFileType(reader, dummyImageFile); const fileTypeInfo = await getFileType(dummyImageFile);
const { thumbnail: newThumbnail } = await generateThumbnail( const { thumbnail: newThumbnail } = await generateThumbnail(
reader,
dummyImageFile, dummyImageFile,
fileTypeInfo fileTypeInfo
); );

View file

@ -1,6 +1,79 @@
import { ElectronFile } from 'types/upload'; import { ElectronFile } from 'types/upload';
import { logError } from 'utils/sentry';
export async function getUint8ArrayView( export async function getUint8ArrayView(
file: Blob | ElectronFile
): Promise<Uint8Array> {
try {
return new Uint8Array(await file.arrayBuffer());
} catch (e) {
logError(e, 'reading file blob failed', {
fileSize: convertBytesToHumanReadable(file.size),
});
throw e;
}
}
export function getFileStream(file: File, chunkSize: number) {
const fileChunkReader = fileChunkReaderMaker(file, chunkSize);
const stream = new ReadableStream<Uint8Array>({
async pull(controller: ReadableStreamDefaultController) {
const chunk = await fileChunkReader.next();
if (chunk.done) {
controller.close();
} else {
controller.enqueue(chunk.value);
}
},
});
const chunkCount = Math.ceil(file.size / chunkSize);
return {
stream,
chunkCount,
};
}
export async function getElectronFileStream(
file: ElectronFile,
chunkSize: number
) {
const chunkCount = Math.ceil(file.size / chunkSize);
return {
stream: await file.stream(),
chunkCount,
};
}
async function* fileChunkReaderMaker(file: File, chunkSize: number) {
let offset = 0;
while (offset < file.size) {
const blob = file.slice(offset, chunkSize + offset);
const fileChunk = await getUint8ArrayView(blob);
yield fileChunk;
offset += chunkSize;
}
return null;
}
// Temporary fix for window not defined caused on importing from utils/billing
// because this file is accessed inside worker and util/billing imports constants
// which has reference to window object, which cause error inside worker
// TODO: update worker to not read file themselves but rather have filedata passed to them
function convertBytesToHumanReadable(bytes: number, precision = 2): string {
if (bytes === 0) {
return '0 MB';
}
const i = Math.floor(Math.log(bytes) / Math.log(1024));
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
return (bytes / Math.pow(1024, i)).toFixed(precision) + ' ' + sizes[i];
}
// depreciated
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async function getUint8ArrayViewOld(
reader: FileReader, reader: FileReader,
file: Blob file: Blob
): Promise<Uint8Array> { ): Promise<Uint8Array> {
@ -32,71 +105,3 @@ export async function getUint8ArrayView(
reader.readAsArrayBuffer(file); reader.readAsArrayBuffer(file);
}); });
} }
export function getFileStream(
reader: FileReader,
file: File,
chunkSize: number
) {
const fileChunkReader = fileChunkReaderMaker(reader, file, chunkSize);
const stream = new ReadableStream<Uint8Array>({
async pull(controller: ReadableStreamDefaultController) {
const chunk = await fileChunkReader.next();
if (chunk.done) {
controller.close();
} else {
controller.enqueue(chunk.value);
}
},
});
const chunkCount = Math.ceil(file.size / chunkSize);
return {
stream,
chunkCount,
};
}
export async function getElectronFileStream(
file: ElectronFile,
chunkSize: number
) {
const chunkCount = Math.ceil(file.size / chunkSize);
return {
stream: await file.stream(),
chunkCount,
};
}
async function* fileChunkReaderMaker(
reader: FileReader,
file: File,
chunkSize: number
) {
let offset = 0;
while (offset < file.size) {
const blob = file.slice(offset, chunkSize + offset);
const fileChunk = await getUint8ArrayView(reader, blob);
yield fileChunk;
offset += chunkSize;
}
return null;
}
// Temporary fix for window not defined caused on importing from utils/billing
// because this file is accessed inside worker and util/billing imports constants
// which has reference to window object, which cause error inside worker
// TODO: update worker to not read file themselves but rather have filedata passed to them
export function convertBytesToHumanReadable(
bytes: number,
precision = 2
): string {
if (bytes === 0) {
return '0 MB';
}
const i = Math.floor(Math.log(bytes) / Math.log(1024));
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
return (bytes / Math.pow(1024, i)).toFixed(precision) + ' ' + sizes[i];
}

View file

@ -12,7 +12,6 @@ const TYPE_IMAGE = 'image';
const CHUNK_SIZE_FOR_TYPE_DETECTION = 4100; const CHUNK_SIZE_FOR_TYPE_DETECTION = 4100;
export async function getFileType( export async function getFileType(
reader: FileReader,
receivedFile: File | ElectronFile receivedFile: File | ElectronFile
): Promise<FileTypeInfo> { ): Promise<FileTypeInfo> {
try { try {
@ -20,7 +19,7 @@ export async function getFileType(
let typeResult: FileTypeResult; let typeResult: FileTypeResult;
if (receivedFile instanceof File) { if (receivedFile instanceof File) {
typeResult = await extractFileType(reader, receivedFile); typeResult = await extractFileType(receivedFile);
} else { } else {
typeResult = await extractElectronFileType(receivedFile); typeResult = await extractElectronFileType(receivedFile);
} }
@ -64,9 +63,9 @@ export async function getFileType(
} }
} }
async function extractFileType(reader: FileReader, file: File) { async function extractFileType(file: File) {
const fileChunkBlob = file.slice(0, CHUNK_SIZE_FOR_TYPE_DETECTION); const fileChunkBlob = file.slice(0, CHUNK_SIZE_FOR_TYPE_DETECTION);
return getFileTypeFromBlob(reader, fileChunkBlob); return getFileTypeFromBlob(fileChunkBlob);
} }
async function extractElectronFileType(file: ElectronFile) { async function extractElectronFileType(file: ElectronFile) {
@ -77,9 +76,9 @@ async function extractElectronFileType(file: ElectronFile) {
return fileTypeResult; return fileTypeResult;
} }
async function getFileTypeFromBlob(reader: FileReader, fileBlob: Blob) { async function getFileTypeFromBlob(fileBlob: Blob) {
try { try {
const initialFiledata = await getUint8ArrayView(reader, fileBlob); const initialFiledata = await getUint8ArrayView(fileBlob);
return await FileType.fromBuffer(initialFiledata); return await FileType.fromBuffer(initialFiledata);
} catch (e) { } catch (e) {
throw Error(CustomError.TYPE_DETECTION_FAILED); throw Error(CustomError.TYPE_DETECTION_FAILED);

View file

@ -38,8 +38,7 @@ export async function updateCreationTimeWithExif(
} else { } else {
const fileURL = await downloadManager.getFile(file)[0]; const fileURL = await downloadManager.getFile(file)[0];
const fileObject = await getFileFromURL(fileURL); const fileObject = await getFileFromURL(fileURL);
const reader = new FileReader(); const fileTypeInfo = await getFileType(fileObject);
const fileTypeInfo = await getFileType(reader, fileObject);
const exifData = await getRawExif(fileObject, fileTypeInfo); const exifData = await getRawExif(fileObject, fileTypeInfo);
if (fixOption === FIX_OPTIONS.DATE_TIME_ORIGINAL) { if (fixOption === FIX_OPTIONS.DATE_TIME_ORIGINAL) {
correctCreationTime = getUnixTimeInMicroSeconds( correctCreationTime = getUnixTimeInMicroSeconds(

View file

@ -34,12 +34,10 @@ export function getFilename(file: File | ElectronFile) {
} }
export async function readFile( export async function readFile(
reader: FileReader,
fileTypeInfo: FileTypeInfo, fileTypeInfo: FileTypeInfo,
rawFile: File | ElectronFile rawFile: File | ElectronFile
): Promise<FileInMemory> { ): Promise<FileInMemory> {
const { thumbnail, hasStaticThumbnail } = await generateThumbnail( const { thumbnail, hasStaticThumbnail } = await generateThumbnail(
reader,
rawFile, rawFile,
fileTypeInfo fileTypeInfo
); );
@ -52,12 +50,12 @@ export async function readFile(
FILE_READER_CHUNK_SIZE FILE_READER_CHUNK_SIZE
); );
} else { } else {
filedata = await rawFile.arrayBuffer(); filedata = await getUint8ArrayView(rawFile);
} }
} else if (rawFile.size > MULTIPART_PART_SIZE) { } else if (rawFile.size > MULTIPART_PART_SIZE) {
filedata = getFileStream(reader, rawFile, FILE_READER_CHUNK_SIZE); filedata = getFileStream(rawFile, FILE_READER_CHUNK_SIZE);
} else { } else {
filedata = await getUint8ArrayView(reader, rawFile); filedata = await getUint8ArrayView(rawFile);
} }
logUploadInfo(`read file data successfully ${getFileNameSize(rawFile)} `); logUploadInfo(`read file data successfully ${getFileNameSize(rawFile)} `);
@ -73,8 +71,7 @@ export async function extractFileMetadata(
parsedMetadataJSONMap: ParsedMetadataJSONMap, parsedMetadataJSONMap: ParsedMetadataJSONMap,
rawFile: File | ElectronFile, rawFile: File | ElectronFile,
collectionID: number, collectionID: number,
fileTypeInfo: FileTypeInfo, fileTypeInfo: FileTypeInfo
reader: FileReader
) { ) {
const originalName = getFileOriginalName(rawFile); const originalName = getFileOriginalName(rawFile);
const googleMetadata = const googleMetadata =
@ -83,8 +80,7 @@ export async function extractFileMetadata(
) ?? {}; ) ?? {};
const extractedMetadata: Metadata = await extractMetadata( const extractedMetadata: Metadata = await extractMetadata(
rawFile, rawFile,
fileTypeInfo, fileTypeInfo
reader
); );
for (const [key, value] of Object.entries(googleMetadata)) { for (const [key, value] of Object.entries(googleMetadata)) {

View file

@ -72,12 +72,10 @@ export function getLivePhotoName(imageTitle: string) {
} }
export async function readLivePhoto( export async function readLivePhoto(
reader: FileReader,
fileTypeInfo: FileTypeInfo, fileTypeInfo: FileTypeInfo,
livePhotoAssets: LivePhotoAssets livePhotoAssets: LivePhotoAssets
) { ) {
const { thumbnail, hasStaticThumbnail } = await generateThumbnail( const { thumbnail, hasStaticThumbnail } = await generateThumbnail(
reader,
livePhotoAssets.image, livePhotoAssets.image,
{ {
exactType: fileTypeInfo.imageType, exactType: fileTypeInfo.imageType,
@ -85,15 +83,9 @@ export async function readLivePhoto(
} }
); );
const image = const image = await getUint8ArrayView(livePhotoAssets.image);
livePhotoAssets.image instanceof File
? await getUint8ArrayView(reader, livePhotoAssets.image)
: await livePhotoAssets.image.arrayBuffer();
const video = const video = await getUint8ArrayView(livePhotoAssets.video);
livePhotoAssets.video instanceof File
? await getUint8ArrayView(reader, livePhotoAssets.video)
: await livePhotoAssets.video.arrayBuffer();
return { return {
filedata: await encodeMotionPhoto({ filedata: await encodeMotionPhoto({

View file

@ -33,8 +33,7 @@ const NULL_PARSED_METADATA_JSON: ParsedMetadataJSON = {
export async function extractMetadata( export async function extractMetadata(
receivedFile: File | ElectronFile, receivedFile: File | ElectronFile,
fileTypeInfo: FileTypeInfo, fileTypeInfo: FileTypeInfo
reader: FileReader
) { ) {
let extractedMetadata: ParsedExtractedMetadata = NULL_EXTRACTED_METADATA; let extractedMetadata: ParsedExtractedMetadata = NULL_EXTRACTED_METADATA;
if (fileTypeInfo.fileType === FILE_TYPE.IMAGE) { if (fileTypeInfo.fileType === FILE_TYPE.IMAGE) {
@ -51,7 +50,7 @@ export async function extractMetadata(
); );
} }
const fileHash = await getFileHash(receivedFile, reader); const fileHash = await getFileHash(receivedFile);
const metadata: Metadata = { const metadata: Metadata = {
title: receivedFile.name, title: receivedFile.name,
@ -74,10 +73,7 @@ export const getMetadataJSONMapKey = (
title: string title: string
) => `${collectionID}-${title}`; ) => `${collectionID}-${title}`;
export async function parseMetadataJSON( export async function parseMetadataJSON(receivedFile: File | ElectronFile) {
reader: FileReader,
receivedFile: File | ElectronFile
) {
try { try {
if (!(receivedFile instanceof File)) { if (!(receivedFile instanceof File)) {
receivedFile = new File( receivedFile = new File(
@ -85,18 +81,7 @@ export async function parseMetadataJSON(
receivedFile.name receivedFile.name
); );
} }
const metadataJSON: object = await new Promise((resolve, reject) => { const metadataJSON: object = JSON.parse(await receivedFile.text());
reader.onabort = () => reject(Error('file reading was aborted'));
reader.onerror = () => reject(Error('file reading has failed'));
reader.onload = () => {
const result =
typeof reader.result !== 'string'
? new TextDecoder().decode(reader.result)
: reader.result;
resolve(JSON.parse(result));
};
reader.readAsText(receivedFile as File);
});
const parsedMetadataJSON: ParsedMetadataJSON = const parsedMetadataJSON: ParsedMetadataJSON =
NULL_PARSED_METADATA_JSON; NULL_PARSED_METADATA_JSON;

View file

@ -24,7 +24,6 @@ interface Dimension {
} }
export async function generateThumbnail( export async function generateThumbnail(
reader: FileReader,
file: File | ElectronFile, file: File | ElectronFile,
fileTypeInfo: FileTypeInfo fileTypeInfo: FileTypeInfo
): Promise<{ thumbnail: Uint8Array; hasStaticThumbnail: boolean }> { ): Promise<{ thumbnail: Uint8Array; hasStaticThumbnail: boolean }> {
@ -72,7 +71,7 @@ export async function generateThumbnail(
} }
} }
const thumbnailBlob = await thumbnailCanvasToBlob(canvas); const thumbnailBlob = await thumbnailCanvasToBlob(canvas);
thumbnail = await getUint8ArrayView(reader, thumbnailBlob); thumbnail = await getUint8ArrayView(thumbnailBlob);
if (thumbnail.length === 0) { if (thumbnail.length === 0) {
throw Error('EMPTY THUMBNAIL'); throw Error('EMPTY THUMBNAIL');
} }

View file

@ -157,7 +157,7 @@ class UploadManager {
logUploadInfo(`parseMetadataJSONFiles function executed `); logUploadInfo(`parseMetadataJSONFiles function executed `);
UIService.reset(metadataFiles.length); UIService.reset(metadataFiles.length);
const reader = new FileReader();
for (const { file, collectionID } of metadataFiles) { for (const { file, collectionID } of metadataFiles) {
try { try {
logUploadInfo( logUploadInfo(
@ -165,7 +165,6 @@ class UploadManager {
); );
const parsedMetadataJSONWithTitle = await parseMetadataJSON( const parsedMetadataJSONWithTitle = await parseMetadataJSON(
reader,
file file
); );
if (parsedMetadataJSONWithTitle) { if (parsedMetadataJSONWithTitle) {
@ -201,7 +200,6 @@ class UploadManager {
try { try {
logUploadInfo(`extractMetadataFromFiles executed`); logUploadInfo(`extractMetadataFromFiles executed`);
UIService.reset(mediaFiles.length); UIService.reset(mediaFiles.length);
const reader = new FileReader();
for (const { file, localID, collectionID } of mediaFiles) { for (const { file, localID, collectionID } of mediaFiles) {
try { try {
const { fileTypeInfo, metadata } = await (async () => { const { fileTypeInfo, metadata } = await (async () => {
@ -215,7 +213,6 @@ class UploadManager {
return { fileTypeInfo: null, metadata: null }; return { fileTypeInfo: null, metadata: null };
} }
const fileTypeInfo = await UploadService.getFileType( const fileTypeInfo = await UploadService.getFileType(
reader,
file file
); );
if (fileTypeInfo.fileType === FILE_TYPE.OTHERS) { if (fileTypeInfo.fileType === FILE_TYPE.OTHERS) {
@ -233,8 +230,7 @@ class UploadManager {
(await UploadService.extractFileMetadata( (await UploadService.extractFileMetadata(
file, file,
collectionID, collectionID,
fileTypeInfo, fileTypeInfo
reader
)) || null; )) || null;
return { fileTypeInfo, metadata }; return { fileTypeInfo, metadata };
})(); })();
@ -291,15 +287,14 @@ class UploadManager {
this.cryptoWorkers[i] = cryptoWorker; this.cryptoWorkers[i] = cryptoWorker;
uploadProcesses.push( uploadProcesses.push(
this.uploadNextFileInQueue( this.uploadNextFileInQueue(
await new this.cryptoWorkers[i].comlink(), await new this.cryptoWorkers[i].comlink()
new FileReader()
) )
); );
} }
await Promise.all(uploadProcesses); await Promise.all(uploadProcesses);
} }
private async uploadNextFileInQueue(worker: any, reader: FileReader) { private async uploadNextFileInQueue(worker: any) {
while (this.filesToBeUploaded.length > 0) { while (this.filesToBeUploaded.length > 0) {
let fileWithCollection = this.filesToBeUploaded.pop(); let fileWithCollection = this.filesToBeUploaded.pop();
const { collectionID } = fileWithCollection; const { collectionID } = fileWithCollection;
@ -310,7 +305,6 @@ class UploadManager {
const { fileUploadResult, uploadedFile, skipDecryption } = const { fileUploadResult, uploadedFile, skipDecryption } =
await uploader( await uploader(
worker, worker,
reader,
existingFilesInCollection, existingFilesInCollection,
this.existingFiles, this.existingFiles,
fileWithCollection fileWithCollection

View file

@ -76,32 +76,29 @@ class UploadService {
: getFilename(file); : getFilename(file);
} }
async getFileType(reader: FileReader, file: File | ElectronFile) { async getFileType(file: File | ElectronFile) {
return getFileType(reader, file); return getFileType(file);
} }
async readAsset( async readAsset(
reader: FileReader,
fileTypeInfo: FileTypeInfo, fileTypeInfo: FileTypeInfo,
{ isLivePhoto, file, livePhotoAssets }: UploadAsset { isLivePhoto, file, livePhotoAssets }: UploadAsset
) { ) {
return isLivePhoto return isLivePhoto
? await readLivePhoto(reader, fileTypeInfo, livePhotoAssets) ? await readLivePhoto(fileTypeInfo, livePhotoAssets)
: await readFile(reader, fileTypeInfo, file); : await readFile(fileTypeInfo, file);
} }
async extractFileMetadata( async extractFileMetadata(
file: File | ElectronFile, file: File | ElectronFile,
collectionID: number, collectionID: number,
fileTypeInfo: FileTypeInfo, fileTypeInfo: FileTypeInfo
reader: FileReader
): Promise<Metadata> { ): Promise<Metadata> {
return extractFileMetadata( return extractFileMetadata(
this.parsedMetadataJSONMap, this.parsedMetadataJSONMap,
file, file,
collectionID, collectionID,
fileTypeInfo, fileTypeInfo
reader
); );
} }

View file

@ -24,7 +24,6 @@ interface UploadResponse {
} }
export default async function uploader( export default async function uploader(
worker: any, worker: any,
reader: FileReader,
existingFilesInCollection: EnteFile[], existingFilesInCollection: EnteFile[],
existingFiles: EnteFile[], existingFiles: EnteFile[],
fileWithCollection: FileWithCollection fileWithCollection: FileWithCollection
@ -87,11 +86,7 @@ export default async function uploader(
} }
logUploadInfo(`reading asset ${fileNameSize}`); logUploadInfo(`reading asset ${fileNameSize}`);
const file = await UploadService.readAsset( const file = await UploadService.readAsset(fileTypeInfo, uploadAsset);
reader,
fileTypeInfo,
uploadAsset
);
if (file.hasStaticThumbnail) { if (file.hasStaticThumbnail) {
metadata.hasStaticThumbnail = true; metadata.hasStaticThumbnail = true;

View file

@ -201,13 +201,10 @@ export async function encryptWithRecoveryKey(key: string) {
} }
export default CryptoWorker; export default CryptoWorker;
export async function getFileHash( export async function getFileHash(file: File | ElectronFile) {
file: File | ElectronFile,
reader: FileReader
) {
let filedata: DataStream; let filedata: DataStream;
if (file instanceof File) { if (file instanceof File) {
filedata = getFileStream(reader, file, FILE_READER_CHUNK_SIZE); filedata = getFileStream(file, FILE_READER_CHUNK_SIZE);
} else { } else {
filedata = await getElectronFileStream(file, FILE_READER_CHUNK_SIZE); filedata = await getElectronFileStream(file, FILE_READER_CHUNK_SIZE);
} }

View file

@ -77,7 +77,6 @@ export async function downloadFile(
} }
const fileType = await getFileType( const fileType = await getFileType(
fileReader,
new File([fileBlob], file.metadata.title) new File([fileBlob], file.metadata.title)
); );
if ( if (
@ -98,12 +97,12 @@ export async function downloadFile(
const originalName = fileNameWithoutExtension(file.metadata.title); const originalName = fileNameWithoutExtension(file.metadata.title);
const motionPhoto = await decodeMotionPhoto(fileBlob, originalName); const motionPhoto = await decodeMotionPhoto(fileBlob, originalName);
const image = new File([motionPhoto.image], motionPhoto.imageNameTitle); const image = new File([motionPhoto.image], motionPhoto.imageNameTitle);
const imageType = await getFileType(fileReader, image); const imageType = await getFileType(image);
tempImageURL = URL.createObjectURL( tempImageURL = URL.createObjectURL(
new Blob([motionPhoto.image], { type: imageType.mimeType }) new Blob([motionPhoto.image], { type: imageType.mimeType })
); );
const video = new File([motionPhoto.video], motionPhoto.videoNameTitle); const video = new File([motionPhoto.video], motionPhoto.videoNameTitle);
const videoType = await getFileType(fileReader, video); const videoType = await getFileType(video);
tempVideoURL = URL.createObjectURL( tempVideoURL = URL.createObjectURL(
new Blob([motionPhoto.video], { type: videoType.mimeType }) new Blob([motionPhoto.video], { type: videoType.mimeType })
); );
@ -338,9 +337,8 @@ export async function convertForPreview(
fileBlob: Blob fileBlob: Blob
): Promise<Blob[]> { ): Promise<Blob[]> {
const convertIfHEIC = async (fileName: string, fileBlob: Blob) => { const convertIfHEIC = async (fileName: string, fileBlob: Blob) => {
const reader = new FileReader();
const mimeType = ( const mimeType = (
await getFileType(reader, new File([fileBlob], file.metadata.title)) await getFileType(new File([fileBlob], file.metadata.title))
).exactType; ).exactType;
if (isFileHEIC(mimeType)) { if (isFileHEIC(mimeType)) {
fileBlob = await HEICConverter.convert(fileBlob); fileBlob = await HEICConverter.convert(fileBlob);