From 6108261b9b73f561ef4b7f71a5569dae48abf43f Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 6 Apr 2022 07:08:59 +0530 Subject: [PATCH 01/11] add fileSaver to handle file download --- package.json | 2 ++ src/utils/file/index.ts | 27 +++++++++++++-------------- yarn.lock | 10 ++++++++++ 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 18fc20c4b..9500251bc 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "eslint-plugin-react-hooks": "^4.2.0", "exifr": "^7.1.3", "ffmpeg-wasm": "file:./thirdparty/ffmpeg-wasm", + "file-saver": "^2.0.5", "file-type": "^16.5.3", "formik": "^2.1.5", "heic-convert": "^1.2.4", @@ -67,6 +68,7 @@ "devDependencies": { "@next/bundle-analyzer": "^9.5.3", "@types/debounce-promise": "^3.1.3", + "@types/file-saver": "^2.0.5", "@types/libsodium-wrappers": "^0.7.8", "@types/node": "^14.6.4", "@types/photoswipe": "^4.1.1", diff --git a/src/utils/file/index.ts b/src/utils/file/index.ts index 7397cf0b4..66e3f25c7 100644 --- a/src/utils/file/index.ts +++ b/src/utils/file/index.ts @@ -25,7 +25,7 @@ import { import PublicCollectionDownloadManager from 'services/publicCollectionDownloadManager'; import HEICConverter from 'services/heicConverter/heicConverterService'; import ffmpegService from 'services/ffmpeg/ffmpegService'; - +import FileSaver from 'file-saver'; export function downloadAsFile(filename: string, content: string) { const file = new Blob([content], { type: 'text/plain', @@ -65,7 +65,6 @@ export async function downloadFile( ) ).blob() ); - console.log({ tempURL }); fileURL = tempURL; } } else { @@ -105,10 +104,10 @@ export async function downloadFile( const motionPhoto = await decodeMotionPhoto(fileBlob, originalName); tempImageURL = URL.createObjectURL(new Blob([motionPhoto.image])); tempVideoURL = URL.createObjectURL(new Blob([motionPhoto.video])); - downloadUsingAnchor(motionPhoto.imageNameTitle, tempImageURL); - downloadUsingAnchor(motionPhoto.videoNameTitle, tempVideoURL); + FileSaver.saveAs(motionPhoto.imageNameTitle, tempImageURL); + FileSaver.saveAs(motionPhoto.videoNameTitle, tempVideoURL); } else { - downloadUsingAnchor(file.metadata.title, fileURL); + FileSaver.saveAs(file.metadata.title, fileURL); } tempURL && URL.revokeObjectURL(tempURL); @@ -117,15 +116,15 @@ export async function downloadFile( tempVideoURL && URL.revokeObjectURL(tempVideoURL); } -function downloadUsingAnchor(name: string, link: string) { - const a = document.createElement('a'); - a.style.display = 'none'; - a.href = link; - a.download = name; - document.body.appendChild(a); - a.click(); - a.remove(); -} +// function downloadUsingAnchor(name: string, link: string) { +// const a = document.createElement('a'); +// a.style.display = 'none'; +// a.href = link; +// a.download = name; +// document.body.appendChild(a); +// a.click(); +// a.remove(); +// } export function isFileHEIC(mimeType: string) { return ( diff --git a/yarn.lock b/yarn.lock index 93b84b5a6..32dc4d835 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1353,6 +1353,11 @@ resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== +"@types/file-saver@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@types/file-saver/-/file-saver-2.0.5.tgz#9ee342a5d1314bb0928375424a2f162f97c310c7" + integrity sha512-zv9kNf3keYegP5oThGLaPk8E081DFDuwfqjtiTzm6PoxChdJ1raSuADf2YGCVIyrSynLrgc8JWv296s7Q7pQSQ== + "@types/glob@^7.1.1": version "7.1.4" resolved "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz" @@ -2988,6 +2993,11 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +file-saver@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38" + integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA== + file-selector@^0.2.2: version "0.2.4" resolved "https://registry.npmjs.org/file-selector/-/file-selector-0.2.4.tgz" From 5633dcda1995c1ac1772c88f92174c57e1e6e080 Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 6 Apr 2022 07:17:02 +0530 Subject: [PATCH 02/11] fix parameter ordering --- src/utils/file/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/file/index.ts b/src/utils/file/index.ts index 66e3f25c7..61543e4fc 100644 --- a/src/utils/file/index.ts +++ b/src/utils/file/index.ts @@ -104,10 +104,10 @@ export async function downloadFile( const motionPhoto = await decodeMotionPhoto(fileBlob, originalName); tempImageURL = URL.createObjectURL(new Blob([motionPhoto.image])); tempVideoURL = URL.createObjectURL(new Blob([motionPhoto.video])); - FileSaver.saveAs(motionPhoto.imageNameTitle, tempImageURL); - FileSaver.saveAs(motionPhoto.videoNameTitle, tempVideoURL); + FileSaver.saveAs(tempImageURL, motionPhoto.imageNameTitle); + FileSaver.saveAs(tempVideoURL, motionPhoto.videoNameTitle); } else { - FileSaver.saveAs(file.metadata.title, fileURL); + FileSaver.saveAs(fileURL, file.metadata.title); } tempURL && URL.revokeObjectURL(tempURL); From 34abfea11140ab0203142ba2bb8475bed4770341 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta Date: Wed, 6 Apr 2022 10:17:38 +0530 Subject: [PATCH 03/11] Shoutout to browserstack --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 63e97f177..d90d2e134 100644 --- a/README.md +++ b/README.md @@ -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. 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 +[](https://www.browserstack.com/open-source) From 2fbc709a2e6596e08bedffe3e8299fd2484cb2b7 Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 6 Apr 2022 16:21:05 +0530 Subject: [PATCH 04/11] change data uri type to jpeg to trigger download --- src/services/typeDetectionService.ts | 2 +- src/services/upload/exifService.ts | 2 +- src/utils/file/index.ts | 73 ++++++++++++++-------------- 3 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/services/typeDetectionService.ts b/src/services/typeDetectionService.ts index a9fc46f62..571c3d84f 100644 --- a/src/services/typeDetectionService.ts +++ b/src/services/typeDetectionService.ts @@ -53,7 +53,7 @@ async function extractFileType(reader: FileReader, file: File) { return getFileTypeFromBlob(reader, fileChunkBlob); } -export async function getFileTypeFromBlob(reader: FileReader, fileBlob: Blob) { +async function getFileTypeFromBlob(reader: FileReader, fileBlob: Blob) { try { const initialFiledata = await getUint8ArrayView(reader, fileBlob); return await FileType.fromBuffer(initialFiledata); diff --git a/src/services/upload/exifService.ts b/src/services/upload/exifService.ts index 1abb8dfb0..92e07b0d6 100644 --- a/src/services/upload/exifService.ts +++ b/src/services/upload/exifService.ts @@ -83,7 +83,7 @@ export async function convertImageToDataURL(reader: FileReader, url: string) { return dataURL; } -function dataURIToBlob(dataURI) { +export function dataURIToBlob(dataURI) { // convert base64 to raw binary data held in a string // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this const byteString = atob(dataURI.split(',')[1]); diff --git a/src/utils/file/index.ts b/src/utils/file/index.ts index 61543e4fc..ad3b5ba8d 100644 --- a/src/utils/file/index.ts +++ b/src/utils/file/index.ts @@ -7,13 +7,17 @@ import { PublicMagicMetadataProps, } from 'types/file'; import { decodeMotionPhoto } from 'services/motionPhotoService'; -import { getFileTypeFromBlob } from 'services/typeDetectionService'; +import { getFileType } from 'services/typeDetectionService'; import DownloadManager from 'services/downloadManager'; import { logError } from 'utils/sentry'; import { User } from 'types/user'; import CryptoWorker from 'utils/crypto'; import { getData, LS_KEYS } from 'utils/storage/localStorage'; -import { updateFileCreationDateInEXIF } from 'services/upload/exifService'; +import { + convertImageToDataURL, + dataURIToBlob, + updateFileCreationDateInEXIF, +} from 'services/upload/exifService'; import { TYPE_JPEG, TYPE_JPG, @@ -25,7 +29,6 @@ import { import PublicCollectionDownloadManager from 'services/publicCollectionDownloadManager'; import HEICConverter from 'services/heicConverter/heicConverterService'; import ffmpegService from 'services/ffmpeg/ffmpegService'; -import FileSaver from 'file-saver'; export function downloadAsFile(filename: string, content: string) { const file = new Blob([content], { type: 'text/plain', @@ -50,31 +53,30 @@ export async function downloadFile( ) { let fileURL: string; let tempURL: string; + let fileBlob: Blob; if (accessedThroughSharedURL) { fileURL = await PublicCollectionDownloadManager.getCachedOriginalFile( file )[0]; tempURL; if (!fileURL) { - tempURL = URL.createObjectURL( - await new Response( - await PublicCollectionDownloadManager.downloadFile( - token, - passwordToken, - file - ) - ).blob() - ); + fileBlob = await new Response( + await PublicCollectionDownloadManager.downloadFile( + token, + passwordToken, + file + ) + ).blob(); + tempURL = URL.createObjectURL(fileBlob); fileURL = tempURL; } } else { fileURL = await DownloadManager.getCachedOriginalFile(file)[0]; if (!fileURL) { - tempURL = URL.createObjectURL( - await new Response( - await DownloadManager.downloadFile(file) - ).blob() - ); + fileBlob = await new Response( + await DownloadManager.downloadFile(file) + ).blob(); + tempURL = URL.createObjectURL(fileBlob); fileURL = tempURL; } } @@ -85,8 +87,6 @@ export async function downloadFile( file.pubMagicMetadata?.data.editedTime && (fileType === TYPE_JPEG || fileType === TYPE_JPG) ) { - let fileBlob = await (await fetch(fileURL)).blob(); - fileBlob = await updateFileCreationDateInEXIF( new FileReader(), fileBlob, @@ -99,15 +99,14 @@ export async function downloadFile( let tempVideoURL: string; if (file.metadata.fileType === FILE_TYPE.LIVE_PHOTO) { - const fileBlob = await (await fetch(fileURL)).blob(); const originalName = fileNameWithoutExtension(file.metadata.title); const motionPhoto = await decodeMotionPhoto(fileBlob, originalName); tempImageURL = URL.createObjectURL(new Blob([motionPhoto.image])); tempVideoURL = URL.createObjectURL(new Blob([motionPhoto.video])); - FileSaver.saveAs(tempImageURL, motionPhoto.imageNameTitle); - FileSaver.saveAs(tempVideoURL, motionPhoto.videoNameTitle); + downloadUsingAnchor(tempImageURL, motionPhoto.imageNameTitle); + downloadUsingAnchor(tempVideoURL, motionPhoto.videoNameTitle); } else { - FileSaver.saveAs(fileURL, file.metadata.title); + await downloadUsingAnchor(fileURL, file.metadata.title); } tempURL && URL.revokeObjectURL(tempURL); @@ -116,15 +115,18 @@ export async function downloadFile( tempVideoURL && URL.revokeObjectURL(tempVideoURL); } -// function downloadUsingAnchor(name: string, link: string) { -// const a = document.createElement('a'); -// a.style.display = 'none'; -// a.href = link; -// a.download = name; -// document.body.appendChild(a); -// a.click(); -// a.remove(); -// } +async function downloadUsingAnchor(link: string, name: string) { + let dataURI = await convertImageToDataURL(new FileReader(), link); + dataURI = dataURI.replace(/^data:[^;]*;/, 'data:image/jpeg;'); + link = URL.createObjectURL(dataURIToBlob(dataURI)); + const a = document.createElement('a'); + a.style.display = 'none'; + a.href = link; + a.download = name; + document.body.appendChild(a); + a.click(); + a.remove(); +} export function isFileHEIC(mimeType: string) { return ( @@ -334,11 +336,10 @@ export async function convertForPreview( fileBlob: Blob ): Promise { const convertIfHEIC = async (fileName: string, fileBlob: Blob) => { - const typeFromExtension = getFileExtension(fileName); const reader = new FileReader(); - const mimeType = - (await getFileTypeFromBlob(reader, fileBlob))?.mime ?? - typeFromExtension; + const mimeType = ( + await getFileType(reader, new File([fileBlob], file.metadata.title)) + ).exactType; if (isFileHEIC(mimeType)) { fileBlob = await HEICConverter.convert(fileBlob); } From d8ad04397b23715341d59b60af7c17358b7291cc Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 6 Apr 2022 17:56:04 +0530 Subject: [PATCH 05/11] updated type detection library to return mimeTYpe --- src/constants/upload/index.ts | 6 +++--- src/services/typeDetectionService.ts | 12 ++++++++++-- src/types/upload/index.ts | 1 + 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/constants/upload/index.ts b/src/constants/upload/index.ts index fb9f0a15d..532e6877e 100644 --- a/src/constants/upload/index.ts +++ b/src/constants/upload/index.ts @@ -4,9 +4,9 @@ import { Location, ParsedExtractedMetadata } from 'types/upload'; // list of format that were missed by type-detection for some files. export const FORMAT_MISSED_BY_FILE_TYPE_LIB = [ - { fileType: FILE_TYPE.IMAGE, exactType: 'jpeg' }, - { fileType: FILE_TYPE.IMAGE, exactType: 'jpg' }, - { fileType: FILE_TYPE.VIDEO, exactType: 'webm' }, + { fileType: FILE_TYPE.IMAGE, exactType: 'jpeg', mimeType: 'image/jpeg' }, + { fileType: FILE_TYPE.IMAGE, exactType: 'jpg', mimeType: 'image/jpeg' }, + { 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. diff --git a/src/services/typeDetectionService.ts b/src/services/typeDetectionService.ts index 571c3d84f..5f101cb96 100644 --- a/src/services/typeDetectionService.ts +++ b/src/services/typeDetectionService.ts @@ -32,7 +32,11 @@ export async function getFileType( default: fileType = FILE_TYPE.OTHERS; } - return { fileType, exactType: typeResult.ext }; + return { + fileType, + exactType: typeResult.ext, + mimeType: typeResult.mime, + }; } catch (e) { const fileFormat = getFileExtension(receivedFile.name); const formatMissedByTypeDetection = FORMAT_MISSED_BY_FILE_TYPE_LIB.find( @@ -44,7 +48,11 @@ export async function getFileType( logError(e, CustomError.TYPE_DETECTION_FAILED, { fileFormat, }); - return { fileType: FILE_TYPE.OTHERS, exactType: fileFormat }; + return { + fileType: FILE_TYPE.OTHERS, + exactType: fileFormat, + mimeType: receivedFile.type, + }; } } diff --git a/src/types/upload/index.ts b/src/types/upload/index.ts index 35a4692a6..07b7ed420 100644 --- a/src/types/upload/index.ts +++ b/src/types/upload/index.ts @@ -48,6 +48,7 @@ export interface MultipartUploadURLs { export interface FileTypeInfo { fileType: FILE_TYPE; exactType: string; + mimeType: string; imageType?: string; videoType?: string; } From ee67ca63ab7d011a674d6bea5b975213872aeb96 Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 6 Apr 2022 17:56:22 +0530 Subject: [PATCH 06/11] update download fileBlob with correct type --- src/utils/file/index.ts | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/utils/file/index.ts b/src/utils/file/index.ts index ad3b5ba8d..d13aea9c4 100644 --- a/src/utils/file/index.ts +++ b/src/utils/file/index.ts @@ -13,11 +13,7 @@ import { logError } from 'utils/sentry'; import { User } from 'types/user'; import CryptoWorker from 'utils/crypto'; import { getData, LS_KEYS } from 'utils/storage/localStorage'; -import { - convertImageToDataURL, - dataURIToBlob, - updateFileCreationDateInEXIF, -} from 'services/upload/exifService'; +import { updateFileCreationDateInEXIF } from 'services/upload/exifService'; import { TYPE_JPEG, TYPE_JPG, @@ -67,6 +63,14 @@ export async function downloadFile( file ) ).blob(); + fileBlob = new Blob([fileBlob], { + type: ( + await getFileType( + new FileReader(), + new File([fileBlob], file.metadata.title) + ) + ).mimeType, + }); tempURL = URL.createObjectURL(fileBlob); fileURL = tempURL; } @@ -76,6 +80,14 @@ export async function downloadFile( fileBlob = await new Response( await DownloadManager.downloadFile(file) ).blob(); + fileBlob = new Blob([fileBlob], { + type: ( + await getFileType( + new FileReader(), + new File([fileBlob], file.metadata.title) + ) + ).mimeType, + }); tempURL = URL.createObjectURL(fileBlob); fileURL = tempURL; } @@ -116,9 +128,6 @@ export async function downloadFile( } async function downloadUsingAnchor(link: string, name: string) { - let dataURI = await convertImageToDataURL(new FileReader(), link); - dataURI = dataURI.replace(/^data:[^;]*;/, 'data:image/jpeg;'); - link = URL.createObjectURL(dataURIToBlob(dataURI)); const a = document.createElement('a'); a.style.display = 'none'; a.href = link; From c3d22d100d60fdd9ed84ed11da0c6ecb11ebc9ff Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 6 Apr 2022 18:04:05 +0530 Subject: [PATCH 07/11] make mimeType optional FileTypeInfo --- src/types/upload/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/upload/index.ts b/src/types/upload/index.ts index 07b7ed420..6d7082a72 100644 --- a/src/types/upload/index.ts +++ b/src/types/upload/index.ts @@ -48,7 +48,7 @@ export interface MultipartUploadURLs { export interface FileTypeInfo { fileType: FILE_TYPE; exactType: string; - mimeType: string; + mimeType?: string; imageType?: string; videoType?: string; } From c0b24546efc1dfb214a12bafc537e0a3d18cfede Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 6 Apr 2022 18:36:53 +0530 Subject: [PATCH 08/11] remove file-saver --- package.json | 2 -- yarn.lock | 10 ---------- 2 files changed, 12 deletions(-) diff --git a/package.json b/package.json index 9500251bc..18fc20c4b 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,6 @@ "eslint-plugin-react-hooks": "^4.2.0", "exifr": "^7.1.3", "ffmpeg-wasm": "file:./thirdparty/ffmpeg-wasm", - "file-saver": "^2.0.5", "file-type": "^16.5.3", "formik": "^2.1.5", "heic-convert": "^1.2.4", @@ -68,7 +67,6 @@ "devDependencies": { "@next/bundle-analyzer": "^9.5.3", "@types/debounce-promise": "^3.1.3", - "@types/file-saver": "^2.0.5", "@types/libsodium-wrappers": "^0.7.8", "@types/node": "^14.6.4", "@types/photoswipe": "^4.1.1", diff --git a/yarn.lock b/yarn.lock index 32dc4d835..93b84b5a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1353,11 +1353,6 @@ resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== -"@types/file-saver@^2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@types/file-saver/-/file-saver-2.0.5.tgz#9ee342a5d1314bb0928375424a2f162f97c310c7" - integrity sha512-zv9kNf3keYegP5oThGLaPk8E081DFDuwfqjtiTzm6PoxChdJ1raSuADf2YGCVIyrSynLrgc8JWv296s7Q7pQSQ== - "@types/glob@^7.1.1": version "7.1.4" resolved "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz" @@ -2993,11 +2988,6 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -file-saver@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38" - integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA== - file-selector@^0.2.2: version "0.2.4" resolved "https://registry.npmjs.org/file-selector/-/file-selector-0.2.4.tgz" From 0168247facd278b2dbf22970167d06c49fd7df9d Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 6 Apr 2022 19:47:34 +0530 Subject: [PATCH 09/11] refactor downloadFile --- src/utils/file/index.ts | 93 ++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/src/utils/file/index.ts b/src/utils/file/index.ts index d13aea9c4..6f426342a 100644 --- a/src/utils/file/index.ts +++ b/src/utils/file/index.ts @@ -13,7 +13,10 @@ import { logError } from 'utils/sentry'; import { User } from 'types/user'; import CryptoWorker from 'utils/crypto'; import { getData, LS_KEYS } from 'utils/storage/localStorage'; -import { updateFileCreationDateInEXIF } from 'services/upload/exifService'; +import { + convertImageToDataURL, + updateFileCreationDateInEXIF, +} from 'services/upload/exifService'; import { TYPE_JPEG, TYPE_JPG, @@ -47,14 +50,13 @@ export async function downloadFile( token?: string, passwordToken?: string ) { - let fileURL: string; - let tempURL: string; let fileBlob: Blob; + const fileReader = new FileReader(); if (accessedThroughSharedURL) { - fileURL = await PublicCollectionDownloadManager.getCachedOriginalFile( - file - )[0]; - tempURL; + const fileURL = + await PublicCollectionDownloadManager.getCachedOriginalFile( + file + )[0]; if (!fileURL) { fileBlob = await new Response( await PublicCollectionDownloadManager.downloadFile( @@ -63,74 +65,81 @@ export async function downloadFile( file ) ).blob(); - fileBlob = new Blob([fileBlob], { - type: ( - await getFileType( - new FileReader(), - new File([fileBlob], file.metadata.title) - ) - ).mimeType, - }); - tempURL = URL.createObjectURL(fileBlob); - fileURL = tempURL; + } else { + fileBlob = await (await fetch(fileURL)).blob(); } } else { - fileURL = await DownloadManager.getCachedOriginalFile(file)[0]; + const fileURL = await DownloadManager.getCachedOriginalFile(file)[0]; if (!fileURL) { fileBlob = await new Response( await DownloadManager.downloadFile(file) ).blob(); - fileBlob = new Blob([fileBlob], { - type: ( - await getFileType( - new FileReader(), - new File([fileBlob], file.metadata.title) - ) - ).mimeType, - }); - tempURL = URL.createObjectURL(fileBlob); - fileURL = tempURL; + } else { + fileBlob = await (await fetch(fileURL)).blob(); } } - const fileType = getFileExtension(file.metadata.title); - let tempEditedFileURL: string; + const fileType = await getFileType( + fileReader, + new File([fileBlob], file.metadata.title) + ); if ( file.pubMagicMetadata?.data.editedTime && - (fileType === TYPE_JPEG || fileType === TYPE_JPG) + (fileType.exactType === TYPE_JPEG || fileType.exactType === TYPE_JPG) ) { fileBlob = await updateFileCreationDateInEXIF( - new FileReader(), + fileReader, fileBlob, new Date(file.pubMagicMetadata.data.editedTime / 1000) ); - tempEditedFileURL = URL.createObjectURL(fileBlob); - fileURL = tempEditedFileURL; } let tempImageURL: string; let tempVideoURL: string; + let tempURL: string; if (file.metadata.fileType === FILE_TYPE.LIVE_PHOTO) { const originalName = fileNameWithoutExtension(file.metadata.title); const motionPhoto = await decodeMotionPhoto(fileBlob, originalName); - tempImageURL = URL.createObjectURL(new Blob([motionPhoto.image])); - tempVideoURL = URL.createObjectURL(new Blob([motionPhoto.video])); - downloadUsingAnchor(tempImageURL, motionPhoto.imageNameTitle); - downloadUsingAnchor(tempVideoURL, motionPhoto.videoNameTitle); + const image = new File([motionPhoto.image], motionPhoto.imageNameTitle); + const imageType = await getFileType(fileReader, image); + tempImageURL = URL.createObjectURL( + 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( + fileReader, + tempImageURL, + motionPhoto.imageNameTitle + ); + downloadUsingAnchor( + fileReader, + tempVideoURL, + motionPhoto.videoNameTitle + ); } else { - await downloadUsingAnchor(fileURL, file.metadata.title); + fileBlob = new Blob([fileBlob], { type: fileType.mimeType }); + tempURL = URL.createObjectURL(fileBlob); + await downloadUsingAnchor(fileReader, tempURL, file.metadata.title); } tempURL && URL.revokeObjectURL(tempURL); - tempEditedFileURL && URL.revokeObjectURL(tempEditedFileURL); tempImageURL && URL.revokeObjectURL(tempImageURL); tempVideoURL && URL.revokeObjectURL(tempVideoURL); } -async function downloadUsingAnchor(link: string, name: string) { +async function downloadUsingAnchor( + fileReader: FileReader, + link: string, + name: string +) { + const dataURI = await convertImageToDataURL(fileReader, link); const a = document.createElement('a'); a.style.display = 'none'; - a.href = link; + a.href = dataURI; a.download = name; document.body.appendChild(a); a.click(); From 4e7be7f99dfeb353e9a5356bd411f022a5d59320 Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 6 Apr 2022 19:59:14 +0530 Subject: [PATCH 10/11] download blobURL direct instead of converting it to dataURI --- src/utils/file/index.ts | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/src/utils/file/index.ts b/src/utils/file/index.ts index 6f426342a..2975c25f1 100644 --- a/src/utils/file/index.ts +++ b/src/utils/file/index.ts @@ -13,10 +13,7 @@ import { logError } from 'utils/sentry'; import { User } from 'types/user'; import CryptoWorker from 'utils/crypto'; import { getData, LS_KEYS } from 'utils/storage/localStorage'; -import { - convertImageToDataURL, - updateFileCreationDateInEXIF, -} from 'services/upload/exifService'; +import { updateFileCreationDateInEXIF } from 'services/upload/exifService'; import { TYPE_JPEG, TYPE_JPG, @@ -110,20 +107,12 @@ export async function downloadFile( tempVideoURL = URL.createObjectURL( new Blob([motionPhoto.video], { type: videoType.mimeType }) ); - downloadUsingAnchor( - fileReader, - tempImageURL, - motionPhoto.imageNameTitle - ); - downloadUsingAnchor( - fileReader, - tempVideoURL, - motionPhoto.videoNameTitle - ); + downloadUsingAnchor(tempImageURL, motionPhoto.imageNameTitle); + downloadUsingAnchor(tempVideoURL, motionPhoto.videoNameTitle); } else { fileBlob = new Blob([fileBlob], { type: fileType.mimeType }); tempURL = URL.createObjectURL(fileBlob); - await downloadUsingAnchor(fileReader, tempURL, file.metadata.title); + downloadUsingAnchor(tempURL, file.metadata.title); } tempURL && URL.revokeObjectURL(tempURL); @@ -131,15 +120,10 @@ export async function downloadFile( tempVideoURL && URL.revokeObjectURL(tempVideoURL); } -async function downloadUsingAnchor( - fileReader: FileReader, - link: string, - name: string -) { - const dataURI = await convertImageToDataURL(fileReader, link); +function downloadUsingAnchor(link: string, name: string) { const a = document.createElement('a'); a.style.display = 'none'; - a.href = dataURI; + a.href = link; a.download = name; document.body.appendChild(a); a.click(); From 3277ab0f5087010ed2987c5fa998f5c42becc18c Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 6 Apr 2022 20:00:57 +0530 Subject: [PATCH 11/11] dont need to be exported --- src/services/upload/exifService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/upload/exifService.ts b/src/services/upload/exifService.ts index 92e07b0d6..8554b424f 100644 --- a/src/services/upload/exifService.ts +++ b/src/services/upload/exifService.ts @@ -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 dataURL = await new Promise((resolve) => { reader.onload = () => resolve(reader.result as string); @@ -83,7 +83,7 @@ export async function convertImageToDataURL(reader: FileReader, url: string) { return dataURL; } -export function dataURIToBlob(dataURI) { +function dataURIToBlob(dataURI) { // convert base64 to raw binary data held in a string // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this const byteString = atob(dataURI.split(',')[1]);