Merge pull request #557 from ente-io/array-buffer
Move to using arrayBuffer instead of readAsArrayBuffer
This commit is contained in:
commit
9a4e7f946d
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
|
|
|
@ -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];
|
|
||||||
}
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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({
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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');
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue