commit
b8cde01eb6
|
@ -51,3 +51,8 @@ If you would like to motivate us to keep building, you can do so by [starring](h
|
||||||
Follow us on [Twitter](https://twitter.com/enteio) and join [r/enteio](https://reddit.com/r/enteio) to get regular updates, connect with other customers, and discuss your ideas.
|
Follow us on [Twitter](https://twitter.com/enteio) and join [r/enteio](https://reddit.com/r/enteio) to get regular updates, connect with other customers, and discuss your ideas.
|
||||||
|
|
||||||
An important part of our journey is to build better software by consistently listening to community feedback. Please feel free to [share your thoughts](mailto:feedback@ente.io) with us at any time.
|
An important part of our journey is to build better software by consistently listening to community feedback. Please feel free to [share your thoughts](mailto:feedback@ente.io) with us at any time.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Cross-browser testing provided by
|
||||||
|
[<img src="https://d98b8t1nnulk5.cloudfront.net/production/images/layout/logo-header.png?1469004780" width="115" height="25">](https://www.browserstack.com/open-source)
|
||||||
|
|
|
@ -4,9 +4,9 @@ import { Location, ParsedExtractedMetadata } from 'types/upload';
|
||||||
|
|
||||||
// list of format that were missed by type-detection for some files.
|
// list of format that were missed by type-detection for some files.
|
||||||
export const FORMAT_MISSED_BY_FILE_TYPE_LIB = [
|
export const FORMAT_MISSED_BY_FILE_TYPE_LIB = [
|
||||||
{ fileType: FILE_TYPE.IMAGE, exactType: 'jpeg' },
|
{ fileType: FILE_TYPE.IMAGE, exactType: 'jpeg', mimeType: 'image/jpeg' },
|
||||||
{ fileType: FILE_TYPE.IMAGE, exactType: 'jpg' },
|
{ fileType: FILE_TYPE.IMAGE, exactType: 'jpg', mimeType: 'image/jpeg' },
|
||||||
{ fileType: FILE_TYPE.VIDEO, exactType: 'webm' },
|
{ fileType: FILE_TYPE.VIDEO, exactType: 'webm', mimeType: 'video/webm' },
|
||||||
];
|
];
|
||||||
|
|
||||||
// this is the chunk size of the un-encrypted file which is read and encrypted before uploading it as a single part.
|
// this is the chunk size of the un-encrypted file which is read and encrypted before uploading it as a single part.
|
||||||
|
|
|
@ -32,7 +32,11 @@ export async function getFileType(
|
||||||
default:
|
default:
|
||||||
fileType = FILE_TYPE.OTHERS;
|
fileType = FILE_TYPE.OTHERS;
|
||||||
}
|
}
|
||||||
return { fileType, exactType: typeResult.ext };
|
return {
|
||||||
|
fileType,
|
||||||
|
exactType: typeResult.ext,
|
||||||
|
mimeType: typeResult.mime,
|
||||||
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const fileFormat = getFileExtension(receivedFile.name);
|
const fileFormat = getFileExtension(receivedFile.name);
|
||||||
const formatMissedByTypeDetection = FORMAT_MISSED_BY_FILE_TYPE_LIB.find(
|
const formatMissedByTypeDetection = FORMAT_MISSED_BY_FILE_TYPE_LIB.find(
|
||||||
|
@ -44,7 +48,11 @@ export async function getFileType(
|
||||||
logError(e, CustomError.TYPE_DETECTION_FAILED, {
|
logError(e, CustomError.TYPE_DETECTION_FAILED, {
|
||||||
fileFormat,
|
fileFormat,
|
||||||
});
|
});
|
||||||
return { fileType: FILE_TYPE.OTHERS, exactType: fileFormat };
|
return {
|
||||||
|
fileType: FILE_TYPE.OTHERS,
|
||||||
|
exactType: fileFormat,
|
||||||
|
mimeType: receivedFile.type,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +61,7 @@ async function extractFileType(reader: FileReader, file: File) {
|
||||||
return getFileTypeFromBlob(reader, fileChunkBlob);
|
return getFileTypeFromBlob(reader, fileChunkBlob);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getFileTypeFromBlob(reader: FileReader, fileBlob: Blob) {
|
async function getFileTypeFromBlob(reader: FileReader, fileBlob: Blob) {
|
||||||
try {
|
try {
|
||||||
const initialFiledata = await getUint8ArrayView(reader, fileBlob);
|
const initialFiledata = await getUint8ArrayView(reader, fileBlob);
|
||||||
return await FileType.fromBuffer(initialFiledata);
|
return await FileType.fromBuffer(initialFiledata);
|
||||||
|
|
|
@ -74,7 +74,7 @@ export async function updateFileCreationDateInEXIF(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function convertImageToDataURL(reader: FileReader, url: string) {
|
async function convertImageToDataURL(reader: FileReader, url: string) {
|
||||||
const blob = await fetch(url).then((r) => r.blob());
|
const blob = await fetch(url).then((r) => r.blob());
|
||||||
const dataURL = await new Promise<string>((resolve) => {
|
const dataURL = await new Promise<string>((resolve) => {
|
||||||
reader.onload = () => resolve(reader.result as string);
|
reader.onload = () => resolve(reader.result as string);
|
||||||
|
|
|
@ -48,6 +48,7 @@ export interface MultipartUploadURLs {
|
||||||
export interface FileTypeInfo {
|
export interface FileTypeInfo {
|
||||||
fileType: FILE_TYPE;
|
fileType: FILE_TYPE;
|
||||||
exactType: string;
|
exactType: string;
|
||||||
|
mimeType?: string;
|
||||||
imageType?: string;
|
imageType?: string;
|
||||||
videoType?: string;
|
videoType?: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
PublicMagicMetadataProps,
|
PublicMagicMetadataProps,
|
||||||
} from 'types/file';
|
} from 'types/file';
|
||||||
import { decodeMotionPhoto } from 'services/motionPhotoService';
|
import { decodeMotionPhoto } from 'services/motionPhotoService';
|
||||||
import { getFileTypeFromBlob } from 'services/typeDetectionService';
|
import { getFileType } from 'services/typeDetectionService';
|
||||||
import DownloadManager from 'services/downloadManager';
|
import DownloadManager from 'services/downloadManager';
|
||||||
import { logError } from 'utils/sentry';
|
import { logError } from 'utils/sentry';
|
||||||
import { User } from 'types/user';
|
import { User } from 'types/user';
|
||||||
|
@ -25,7 +25,6 @@ import {
|
||||||
import PublicCollectionDownloadManager from 'services/publicCollectionDownloadManager';
|
import PublicCollectionDownloadManager from 'services/publicCollectionDownloadManager';
|
||||||
import HEICConverter from 'services/heicConverter/heicConverterService';
|
import HEICConverter from 'services/heicConverter/heicConverterService';
|
||||||
import ffmpegService from 'services/ffmpeg/ffmpegService';
|
import ffmpegService from 'services/ffmpeg/ffmpegService';
|
||||||
|
|
||||||
export function downloadAsFile(filename: string, content: string) {
|
export function downloadAsFile(filename: string, content: string) {
|
||||||
const file = new Blob([content], {
|
const file = new Blob([content], {
|
||||||
type: 'text/plain',
|
type: 'text/plain',
|
||||||
|
@ -48,76 +47,80 @@ export async function downloadFile(
|
||||||
token?: string,
|
token?: string,
|
||||||
passwordToken?: string
|
passwordToken?: string
|
||||||
) {
|
) {
|
||||||
let fileURL: string;
|
let fileBlob: Blob;
|
||||||
let tempURL: string;
|
const fileReader = new FileReader();
|
||||||
if (accessedThroughSharedURL) {
|
if (accessedThroughSharedURL) {
|
||||||
fileURL = await PublicCollectionDownloadManager.getCachedOriginalFile(
|
const fileURL =
|
||||||
file
|
await PublicCollectionDownloadManager.getCachedOriginalFile(
|
||||||
)[0];
|
file
|
||||||
tempURL;
|
)[0];
|
||||||
if (!fileURL) {
|
if (!fileURL) {
|
||||||
tempURL = URL.createObjectURL(
|
fileBlob = await new Response(
|
||||||
await new Response(
|
await PublicCollectionDownloadManager.downloadFile(
|
||||||
await PublicCollectionDownloadManager.downloadFile(
|
token,
|
||||||
token,
|
passwordToken,
|
||||||
passwordToken,
|
file
|
||||||
file
|
)
|
||||||
)
|
).blob();
|
||||||
).blob()
|
} else {
|
||||||
);
|
fileBlob = await (await fetch(fileURL)).blob();
|
||||||
console.log({ tempURL });
|
|
||||||
fileURL = tempURL;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fileURL = await DownloadManager.getCachedOriginalFile(file)[0];
|
const fileURL = await DownloadManager.getCachedOriginalFile(file)[0];
|
||||||
if (!fileURL) {
|
if (!fileURL) {
|
||||||
tempURL = URL.createObjectURL(
|
fileBlob = await new Response(
|
||||||
await new Response(
|
await DownloadManager.downloadFile(file)
|
||||||
await DownloadManager.downloadFile(file)
|
).blob();
|
||||||
).blob()
|
} else {
|
||||||
);
|
fileBlob = await (await fetch(fileURL)).blob();
|
||||||
fileURL = tempURL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileType = getFileExtension(file.metadata.title);
|
const fileType = await getFileType(
|
||||||
let tempEditedFileURL: string;
|
fileReader,
|
||||||
|
new File([fileBlob], file.metadata.title)
|
||||||
|
);
|
||||||
if (
|
if (
|
||||||
file.pubMagicMetadata?.data.editedTime &&
|
file.pubMagicMetadata?.data.editedTime &&
|
||||||
(fileType === TYPE_JPEG || fileType === TYPE_JPG)
|
(fileType.exactType === TYPE_JPEG || fileType.exactType === TYPE_JPG)
|
||||||
) {
|
) {
|
||||||
let fileBlob = await (await fetch(fileURL)).blob();
|
|
||||||
|
|
||||||
fileBlob = await updateFileCreationDateInEXIF(
|
fileBlob = await updateFileCreationDateInEXIF(
|
||||||
new FileReader(),
|
fileReader,
|
||||||
fileBlob,
|
fileBlob,
|
||||||
new Date(file.pubMagicMetadata.data.editedTime / 1000)
|
new Date(file.pubMagicMetadata.data.editedTime / 1000)
|
||||||
);
|
);
|
||||||
tempEditedFileURL = URL.createObjectURL(fileBlob);
|
|
||||||
fileURL = tempEditedFileURL;
|
|
||||||
}
|
}
|
||||||
let tempImageURL: string;
|
let tempImageURL: string;
|
||||||
let tempVideoURL: string;
|
let tempVideoURL: string;
|
||||||
|
let tempURL: string;
|
||||||
|
|
||||||
if (file.metadata.fileType === FILE_TYPE.LIVE_PHOTO) {
|
if (file.metadata.fileType === FILE_TYPE.LIVE_PHOTO) {
|
||||||
const fileBlob = await (await fetch(fileURL)).blob();
|
|
||||||
const originalName = fileNameWithoutExtension(file.metadata.title);
|
const originalName = fileNameWithoutExtension(file.metadata.title);
|
||||||
const motionPhoto = await decodeMotionPhoto(fileBlob, originalName);
|
const motionPhoto = await decodeMotionPhoto(fileBlob, originalName);
|
||||||
tempImageURL = URL.createObjectURL(new Blob([motionPhoto.image]));
|
const image = new File([motionPhoto.image], motionPhoto.imageNameTitle);
|
||||||
tempVideoURL = URL.createObjectURL(new Blob([motionPhoto.video]));
|
const imageType = await getFileType(fileReader, image);
|
||||||
downloadUsingAnchor(motionPhoto.imageNameTitle, tempImageURL);
|
tempImageURL = URL.createObjectURL(
|
||||||
downloadUsingAnchor(motionPhoto.videoNameTitle, tempVideoURL);
|
new Blob([motionPhoto.image], { type: imageType.mimeType })
|
||||||
|
);
|
||||||
|
const video = new File([motionPhoto.video], motionPhoto.videoNameTitle);
|
||||||
|
const videoType = await getFileType(fileReader, video);
|
||||||
|
tempVideoURL = URL.createObjectURL(
|
||||||
|
new Blob([motionPhoto.video], { type: videoType.mimeType })
|
||||||
|
);
|
||||||
|
downloadUsingAnchor(tempImageURL, motionPhoto.imageNameTitle);
|
||||||
|
downloadUsingAnchor(tempVideoURL, motionPhoto.videoNameTitle);
|
||||||
} else {
|
} else {
|
||||||
downloadUsingAnchor(file.metadata.title, fileURL);
|
fileBlob = new Blob([fileBlob], { type: fileType.mimeType });
|
||||||
|
tempURL = URL.createObjectURL(fileBlob);
|
||||||
|
downloadUsingAnchor(tempURL, file.metadata.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
tempURL && URL.revokeObjectURL(tempURL);
|
tempURL && URL.revokeObjectURL(tempURL);
|
||||||
tempEditedFileURL && URL.revokeObjectURL(tempEditedFileURL);
|
|
||||||
tempImageURL && URL.revokeObjectURL(tempImageURL);
|
tempImageURL && URL.revokeObjectURL(tempImageURL);
|
||||||
tempVideoURL && URL.revokeObjectURL(tempVideoURL);
|
tempVideoURL && URL.revokeObjectURL(tempVideoURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
function downloadUsingAnchor(name: string, link: string) {
|
function downloadUsingAnchor(link: string, name: string) {
|
||||||
const a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
a.style.display = 'none';
|
a.style.display = 'none';
|
||||||
a.href = link;
|
a.href = link;
|
||||||
|
@ -335,11 +338,10 @@ 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 typeFromExtension = getFileExtension(fileName);
|
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
const mimeType =
|
const mimeType = (
|
||||||
(await getFileTypeFromBlob(reader, fileBlob))?.mime ??
|
await getFileType(reader, new File([fileBlob], file.metadata.title))
|
||||||
typeFromExtension;
|
).exactType;
|
||||||
if (isFileHEIC(mimeType)) {
|
if (isFileHEIC(mimeType)) {
|
||||||
fileBlob = await HEICConverter.convert(fileBlob);
|
fileBlob = await HEICConverter.convert(fileBlob);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue