// external imports import { fileTypeFromBuffer } from "file-type"; // plane imports import { TFileMetaDataLite, TFileSignedURLResponse } from "@plane/types"; /** * @description from the provided signed URL response, generate a payload to be used to upload the file * @param {TFileSignedURLResponse} signedURLResponse * @param {File} file * @returns {FormData} file upload request payload */ export const generateFileUploadPayload = (signedURLResponse: TFileSignedURLResponse, file: File): FormData => { const formData = new FormData(); Object.entries(signedURLResponse.upload_data.fields).forEach(([key, value]) => formData.append(key, value)); formData.append("file", file); return formData; }; /** * @description Detect MIME type from file signature using file-type library * @param {File} file * @returns {Promise} detected MIME type or empty string if unknown */ const detectMimeTypeFromSignature = async (file: File): Promise => { try { // Read first 4KB which is usually sufficient for most file type detection const chunk = file.slice(0, 4096); const buffer = await chunk.arrayBuffer(); const uint8Array = new Uint8Array(buffer); const fileType = await fileTypeFromBuffer(uint8Array); return fileType?.mime || ""; } catch (_error) { return ""; } }; /** * @description Determine the MIME type of a file using multiple detection methods * @param {File} file * @returns {Promise} detected MIME type */ const detectFileType = async (file: File): Promise => { // check if the file has a MIME type if (file.type && file.type.trim() !== "") { return file.type; } // detect from file signature using file-type library try { const signatureType = await detectMimeTypeFromSignature(file); if (signatureType) { return signatureType; } } catch (_error) { console.error("Error detecting file type from signature:", _error); } // fallback for unknown files return "application/octet-stream"; }; /** * @description returns the necessary file meta data to upload a file * @param {File} file * @returns {Promise} payload with file info */ export const getFileMetaDataForUpload = async (file: File): Promise => { const fileType = await detectFileType(file); return { name: file.name, size: file.size, type: fileType, }; }; /** * @description this function returns the assetId from the asset source * @param {string} src * @returns {string} assetId */ export const getAssetIdFromUrl = (src: string): string => { const sourcePaths = src.split("/"); const assetUrl = sourcePaths[sourcePaths.length - 1]; return assetUrl ?? ""; };