diff --git a/lib/media/file-utils.js b/lib/media/file-utils.js --- a/lib/media/file-utils.js +++ b/lib/media/file-utils.js @@ -172,6 +172,16 @@ return replaceExtension(filename, ext); } +const basenameRegex = /[^a-z0-9._-]/gi; +function sanitizeFilename(filename: ?string, mime: string): string { + if (!filename) { + // Generate a random filename and deduce the extension from the mime type. + const randomName = Math.random().toString(36).slice(-5); + filename = readableFilename(randomName, mime) || randomName; + } + return filename.replace(basenameRegex, '_'); +} + const extRegex = /\.([0-9a-z]+)$/i; function extensionFromFilename(filename: string): ?string { const matches = filename.match(extRegex); @@ -212,6 +222,7 @@ fileInfoFromData, replaceExtension, readableFilename, + sanitizeFilename, extensionFromFilename, pathFromURI, filenameFromPathOrURI, diff --git a/lib/types/media-types.js b/lib/types/media-types.js --- a/lib/types/media-types.js +++ b/lib/types/media-types.js @@ -213,7 +213,7 @@ | { +step: 'photo_library', +dimensions: Dimensions, - +filename: string, + +filename: ?string, +uri: string, +mediaNativeID: string, +selectTime: number, // ms timestamp @@ -223,7 +223,7 @@ | { +step: 'video_library', +dimensions: Dimensions, - +filename: string, + +filename: ?string, +uri: string, +mediaNativeID: string, +selectTime: number, // ms timestamp diff --git a/native/media/media-utils.js b/native/media/media-utils.js --- a/native/media/media-utils.js +++ b/native/media/media-utils.js @@ -3,7 +3,7 @@ import invariant from 'invariant'; import { Image } from 'react-native'; -import { pathFromURI, readableFilename } from 'lib/media/file-utils'; +import { pathFromURI, sanitizeFilename } from 'lib/media/file-utils'; import type { Dimensions, MediaMissionStep, @@ -89,8 +89,7 @@ ); const shouldDisposePath = initialURI !== uploadURI ? pathFromURI(uploadURI) : null; - const filename = readableFilename(selection.filename, mime); - invariant(filename, `could not construct filename for ${mime}`); + const filename = sanitizeFilename(selection.filename, mime); if (mediaType === 'video') { invariant(uploadThumbnailURI, 'video should have uploadThumbnailURI'); sendResult({ @@ -170,11 +169,12 @@ } if (mediaType === 'video') { + const filename = sanitizeFilename(selection.filename, mime); const { steps: videoSteps, result: videoResult } = await processVideo( { uri: initialURI, mime, - filename: selection.filename, + filename, fileSize, dimensions, hasWiFi: config.hasWiFi,