UNPKG

@wordpress/media-utils

Version:
176 lines (161 loc) 5.29 kB
/** * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n'; import { createBlobURL, revokeBlobURL } from '@wordpress/blob'; /** * Internal dependencies */ import type { AdditionalData, Attachment, OnChangeHandler, OnErrorHandler, } from './types'; import { uploadToServer } from './upload-to-server'; import { validateMimeType } from './validate-mime-type'; import { validateMimeTypeForUser } from './validate-mime-type-for-user'; import { validateFileSize } from './validate-file-size'; import { UploadError } from './upload-error'; declare global { interface Window { __clientSideMediaProcessing?: boolean; } } interface UploadMediaArgs { // Additional data to include in the request. additionalData?: AdditionalData; // Array with the types of media that can be uploaded, if unset all types are allowed. allowedTypes?: string[]; // List of files. filesList: File[]; // Maximum upload size in bytes allowed for the site. maxUploadFileSize?: number; // Function called when an error happens. onError?: OnErrorHandler; // Function called each time a file or a temporary representation of the file is available. onFileChange?: OnChangeHandler; // List of allowed mime types and file extensions. wpAllowedMimeTypes?: Record< string, string > | null; // Abort signal. signal?: AbortSignal; // Whether to allow multiple files to be uploaded. multiple?: boolean; } /** * Upload a media file when the file upload button is activated * or when adding a file to the editor via drag & drop. * * @param $0 Parameters object passed to the function. * @param $0.allowedTypes Array with the types of media that can be uploaded, if unset all types are allowed. * @param $0.additionalData Additional data to include in the request. * @param $0.filesList List of files. * @param $0.maxUploadFileSize Maximum upload size in bytes allowed for the site. * @param $0.onError Function called when an error happens. * @param $0.onFileChange Function called each time a file or a temporary representation of the file is available. * @param $0.wpAllowedMimeTypes List of allowed mime types and file extensions. * @param $0.signal Abort signal. * @param $0.multiple Whether to allow multiple files to be uploaded. */ export function uploadMedia( { wpAllowedMimeTypes, allowedTypes, additionalData = {}, filesList, maxUploadFileSize, onError, onFileChange, signal, multiple = true, }: UploadMediaArgs ) { if ( ! multiple && filesList.length > 1 ) { onError?.( new Error( __( 'Only one file can be used here.' ) ) ); return; } const validFiles = []; const filesSet: Array< Partial< Attachment > | null > = []; const setAndUpdateFiles = ( index: number, value: Attachment | null ) => { // For client-side media processing, this is handled by the upload-media package. if ( ! window.__clientSideMediaProcessing ) { if ( filesSet[ index ]?.url ) { revokeBlobURL( filesSet[ index ].url ); } } filesSet[ index ] = value; onFileChange?.( filesSet.filter( ( attachment ) => attachment !== null ) ); }; for ( const mediaFile of filesList ) { // Verify if user is allowed to upload this mime type. // Defer to the server when type not detected. try { validateMimeTypeForUser( mediaFile, wpAllowedMimeTypes ); } catch ( error: unknown ) { onError?.( error as Error ); continue; } // Check if the caller (e.g. a block) supports this mime type. // Defer to the server when type not detected. try { validateMimeType( mediaFile, allowedTypes ); } catch ( error: unknown ) { onError?.( error as Error ); continue; } // Verify if file is greater than the maximum file upload size allowed for the site. try { validateFileSize( mediaFile, maxUploadFileSize ); } catch ( error: unknown ) { onError?.( error as Error ); continue; } validFiles.push( mediaFile ); // For client-side media processing, this is handled by the upload-media package. if ( ! window.__clientSideMediaProcessing ) { // Set temporary URL to create placeholder media file, this is replaced // with final file from media gallery when upload is `done` below. filesSet.push( { url: createBlobURL( mediaFile ) } ); onFileChange?.( filesSet as Array< Partial< Attachment > > ); } } validFiles.map( async ( file, index ) => { try { const attachment = await uploadToServer( file, additionalData, signal ); setAndUpdateFiles( index, attachment ); } catch ( error ) { // Reset to empty on failure. setAndUpdateFiles( index, null ); // @wordpress/api-fetch throws any response that isn't in the 200 range as-is. let message: string; if ( typeof error === 'object' && error !== null && 'message' in error ) { message = typeof error.message === 'string' ? error.message : String( error.message ); } else { message = sprintf( // translators: %s: file name __( 'Error while uploading file %s to the media library.' ), file.name ); } onError?.( new UploadError( { code: 'GENERAL', message, file, cause: error instanceof Error ? error : undefined, } ) ); } } ); }