diff --git a/src/api/MicroPubApi.js b/src/api/MicroPubApi.js index 3509f104..425f5a52 100644 --- a/src/api/MicroPubApi.js +++ b/src/api/MicroPubApi.js @@ -1,7 +1,8 @@ -import { Alert, Platform } from 'react-native'; +import { Alert } from 'react-native'; import axios from 'axios'; import { DOMParser } from "@xmldom/xmldom"; import App from "./../stores/App"; +import { buildUploadFileName } from "../utils/file_names" export const FETCH_ERROR = 2 export const POST_ERROR = 3 @@ -330,13 +331,9 @@ class MicroPubApi { async upload_media(service, file, destination) { const data = new FormData() - // Get extension from file name, for example: 12345.jpg - let extension = file.uri.split('.').pop() - if (Platform.OS === "android" && file.name != null && file.name !== "") { - extension = file.name.split('.').pop() - } + const file_name = buildUploadFileName(file, Date.now()) data.append("file", { - name: `media.${extension.toLowerCase()}`, + name: file_name, type: file.type, uri: file.uri, }) diff --git a/src/stores/models/posting/uploadLargeMediaTask.js b/src/stores/models/posting/uploadLargeMediaTask.js index 58ba8503..625258b9 100644 --- a/src/stores/models/posting/uploadLargeMediaTask.js +++ b/src/stores/models/posting/uploadLargeMediaTask.js @@ -2,6 +2,7 @@ import { Platform } from "react-native" import RNFS from "react-native-fs" import axios from "axios" import MicroPubApi, { POST_ERROR, FETCH_ERROR } from "../../../api/MicroPubApi" +import { buildUploadFileName, inferExtensionFromType, sanitizeFileName } from "../../../utils/file_names" export const LARGE_UPLOAD_CHUNK_SIZE = 1000 * 1024 export const LARGE_UPLOAD_MAX_SIZE = 1024 * 1024 * 1024 @@ -10,38 +11,6 @@ export const LARGE_UPLOAD_MAX_ATTEMPTS = 45 const wait = ms => new Promise(resolve => setTimeout(resolve, ms)) -export const infer_extension_from_type = (mime = "") => { - if (mime.includes("quicktime")) { - return ".mov" - } - if (mime.includes("mp4")) { - return ".mp4" - } - if (mime.includes("m4v")) { - return ".m4v" - } - if (mime.includes("webm")) { - return ".webm" - } - if (mime.includes("ogg")) { - return ".ogv" - } - return ".mp4" -} - -export const build_file_name = (media, fallback_id) => { - if (media?.fileName) { - return media.fileName - } - if (media?.filename) { - return media.filename - } - if (media?.name) { - return media.name - } - return `upload-${fallback_id}${infer_extension_from_type(media?.type || "")}` -} - export const ensure_local_uri_for_upload = async (media, fallback_name) => { const current_uri = media?.cached_uri || media?.cachedUri || media?.uri if (!current_uri) { @@ -50,8 +19,8 @@ export const ensure_local_uri_for_upload = async (media, fallback_name) => { if (current_uri.startsWith("file://")) { return current_uri } - const target_name = fallback_name || `upload-${Date.now()}${infer_extension_from_type(media?.type || "")}` - const safe_name = target_name.replace(/[^\w.\-]/g, "_") + const target_name = fallback_name || `upload-${Date.now()}${inferExtensionFromType(media?.type || "")}` + const safe_name = sanitizeFileName(target_name) const target_path = `${RNFS.CachesDirectoryPath}/${Date.now()}-${safe_name}` let source_path = current_uri try { @@ -98,7 +67,7 @@ export async function upload_large_media_task({ const active_cancel_source = cancel_source || create_cancel_source() const file_id = Math.floor(Math.random() * 1000000) - const file_name = build_file_name(media, file_id) + const file_name = buildUploadFileName(media, file_id) const file_type = media?.type || "video/mp4" try { diff --git a/src/utils/file_names.js b/src/utils/file_names.js new file mode 100644 index 00000000..9d3fae60 --- /dev/null +++ b/src/utils/file_names.js @@ -0,0 +1,51 @@ +export const inferExtensionFromType = (mime = "") => { + if (mime.includes("quicktime")) { + return ".mov" + } + if (mime.includes("mp4")) { + return ".mp4" + } + if (mime.includes("m4v")) { + return ".m4v" + } + if (mime.includes("webm")) { + return ".webm" + } + if (mime.includes("ogg")) { + return ".ogv" + } + return ".mp4" +} + +const getExtension = name => { + if (!name) { + return "" + } + const parts = name.split(".") + if (parts.length < 2) { + return "" + } + const extension = parts.pop() + if (!extension) { + return "" + } + return `.${extension}` +} + +export const sanitizeFileName = name => { + if (!name) { + return "" + } + return name.trim().replace(/[^\w.\-]/g, "_") +} + +export const buildUploadFileName = (media, fallback_id) => { + const candidate_name = media?.fileName || media?.filename || media?.name + const safe_candidate = sanitizeFileName(candidate_name) + const base_name = safe_candidate || `upload-${fallback_id || Date.now()}` + const extension = getExtension(base_name) + if (!extension) { + return `${base_name}${inferExtensionFromType(media?.type || "")}` + } + return base_name +}