From 3072196cda6fd753fb95a188682ea0f6c41438b8 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Tue, 4 Jul 2023 17:28:41 -0300 Subject: [PATCH] save the file with a similar filename as expected --- app/lib/methods/handleMediaDownload.test.ts | 58 +++++++++++++++++++++ app/lib/methods/handleMediaDownload.ts | 41 +++++++++++++++ app/views/AttachmentView.tsx | 16 +++--- 3 files changed, 107 insertions(+), 8 deletions(-) create mode 100644 app/lib/methods/handleMediaDownload.test.ts diff --git a/app/lib/methods/handleMediaDownload.test.ts b/app/lib/methods/handleMediaDownload.test.ts new file mode 100644 index 000000000..0606e7630 --- /dev/null +++ b/app/lib/methods/handleMediaDownload.test.ts @@ -0,0 +1,58 @@ +import { getFilename } from './handleMediaDownload'; + +describe('Test the getFilename', () => { + it('returns the title without changes', () => { + const { image_type, image_url, title } = { + title: 'help-image.png', + image_url: '/file-upload/oTQmb2zRCsYF4pdHv/help-image-url.png', + image_type: 'image/png' + }; + + const filename = getFilename({ type: 'image', mimeType: image_type, title, url: image_url }); + expect(filename).toBe(title); + }); + + it("returns the title with correct extension based on image_type when the title's extension is wrong", () => { + const { image_type, image_url, title } = { + title: 'help-image.MOV', + image_url: '/file-upload/oTQmb2zRCsYF4pdHv/help-image-url.MOV', + image_type: 'image/png' + }; + + const filename = getFilename({ type: 'image', mimeType: image_type, title, url: image_url }); + expect(filename).toBe('help-image.png'); + }); + + it("returns the filename from image_url when there isn't extension at title", () => { + const { image_type, image_url, title } = { + title: 'help-image', + image_url: '/file-upload/oTQmb2zRCsYF4pdHv/help-image-url.png', + image_type: 'image/png' + }; + + const filename = getFilename({ type: 'image', mimeType: image_type, title, url: image_url }); + expect(filename).toBe('help-image-url.png'); + }); + + it("returns the filename from image_url with correct extension based on image_type when there isn't extension at title and the image_url's extension is wrong", () => { + const { image_type, image_url, title } = { + title: 'help-image', + image_url: '/file-upload/oTQmb2zRCsYF4pdHv/help-image-url.MOV', + image_type: 'image/png' + }; + + const filename = getFilename({ type: 'image', mimeType: image_type, title, url: image_url }); + expect(filename).toBe('help-image-url.png'); + }); + + it("returns the filename from image_url and based on the image_type when there isn't extension either at title and image_url", () => { + const { image_type, image_url, title } = { + title: 'help-image', + image_url: '/file-upload/oTQmb2zRCsYF4pdHv/help-image-url.png', + image_type: 'image/png' + }; + + const filename = getFilename({ type: 'image', mimeType: image_type, title, url: image_url }); + expect(filename).toBe('help-image-url.png'); + }); +}); diff --git a/app/lib/methods/handleMediaDownload.ts b/app/lib/methods/handleMediaDownload.ts index 40f05e36c..e7d94c1b1 100644 --- a/app/lib/methods/handleMediaDownload.ts +++ b/app/lib/methods/handleMediaDownload.ts @@ -22,6 +22,42 @@ const sanitizeString = (value: string) => { }; const serverUrlParsedAsPath = (serverURL: string) => `${sanitizeString(serverURL)}/`; +export const getFilename = ({ + title, + url, + type, + mimeType +}: { + title?: string; + url?: string; + type: MediaTypes; + mimeType?: string; +}) => { + const isTitleTyped = mime.lookup(title); + const extension = getExtension(type, mimeType); + if (isTitleTyped && title) { + if (isTitleTyped === mimeType) { + return title; + } + // removing any character sequence after the last dot + const filenameWithoutWrongExtension = title.replace(/\.\w+$/, ''); + return `${filenameWithoutWrongExtension}.${extension}`; + } + + const filenameFromUrl = url?.substring(url.lastIndexOf('/') + 1); + const isFileNameFromUrlTyped = mime.lookup(filenameFromUrl); + if (isFileNameFromUrlTyped && filenameFromUrl) { + if (isFileNameFromUrlTyped === mimeType) { + return filenameFromUrl; + } + // removing any character sequence after the last dot + const filenameWithoutWrongExtension = filenameFromUrl.replace(/\.\w+$/, ''); + return `${filenameWithoutWrongExtension}.${extension}`; + } + + return `${filenameFromUrl}.${extension}`; +}; + const getExtension = (type: MediaTypes, mimeType?: string) => { if (!mimeType) { return defaultType[type]; @@ -34,6 +70,11 @@ const getExtension = (type: MediaTypes, mimeType?: string) => { if (mimeType === 'audio/aac') { return 'm4a'; } + // The return of mime.extension('video/quicktime') is .qt, + // this format the iOS isn't recognize and can't save on gallery + if (mimeType === 'video/quicktime') { + return 'mov'; + } const extension = mime.extension(mimeType); // The mime.extension can return false when there aren't any extension if (!extension) { diff --git a/app/views/AttachmentView.tsx b/app/views/AttachmentView.tsx index a9ec7c1dd..68e0fbaa2 100644 --- a/app/views/AttachmentView.tsx +++ b/app/views/AttachmentView.tsx @@ -2,10 +2,8 @@ import CameraRoll from '@react-native-community/cameraroll'; import { HeaderBackground, useHeaderHeight } from '@react-navigation/elements'; import { StackNavigationOptions } from '@react-navigation/stack'; import { ResizeMode, Video } from 'expo-av'; -import { sha256 } from 'js-sha256'; import React from 'react'; import { PermissionsAndroid, useWindowDimensions, View } from 'react-native'; -import * as mime from 'react-native-mime-types'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { shallowEqual } from 'react-redux'; import RNFetchBlob from 'rn-fetch-blob'; @@ -24,6 +22,7 @@ import EventEmitter from '../lib/methods/helpers/events'; import { getUserSelector } from '../selectors/login'; import { TNavigation } from '../stacks/stackType'; import { useTheme } from '../theme'; +import { getFilename } from '../lib/methods/handleMediaDownload'; const RenderContent = ({ setLoading, @@ -166,13 +165,14 @@ const AttachmentView = (): React.ReactElement => { setLoading(true); try { - const extension = image_url - ? `.${mime.extension(image_type) || 'jpg'}` - : `.${(video_type === 'video/quicktime' && 'mov') || mime.extension(video_type) || 'mp4'}`; - // The return of mime.extension('video/quicktime') is .qt, - // this format the iOS isn't recognize and can't save on gallery + let filename = ''; + if (image_url) { + filename = getFilename({ title: attachment.title, type: 'image', mimeType: image_type, url }); + } else { + filename = getFilename({ title: attachment.title, type: 'video', mimeType: video_type, url }); + } const documentDir = `${RNFetchBlob.fs.dirs.DocumentDir}/`; - const path = `${documentDir + sha256(url) + extension}`; + const path = `${documentDir + filename}`; const file = await RNFetchBlob.config({ path }).fetch('GET', mediaAttachment); await CameraRoll.save(path, { album: 'Rocket.Chat' }); file.flush();