-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Post publish upload media dialog: handle more block types (#65122)
* Post publish upload media dialog: handle more block types * Deduplicate uploads and media filenames * Correctly create File object for fetched media * media-util.js: review suggestions * Add more JSDoc * Fix wrong types * Allow all uploads to finish, even if some fail Co-authored-by: sgomes <sergiomdgomes@git.wordpress.org> Co-authored-by: swissspidy <swissspidy@git.wordpress.org> Co-authored-by: mtias <matveb@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: ntsekouras <ntsekouras@git.wordpress.org>
- Loading branch information
1 parent
b758cca
commit 57e0b9c
Showing
3 changed files
with
354 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
packages/editor/src/components/post-publish-panel/media-util.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { v4 as uuid } from 'uuid'; | ||
|
||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { getFilename } from '@wordpress/url'; | ||
|
||
/** | ||
* Generate a list of unique basenames given a list of URLs. | ||
* | ||
* We want all basenames to be unique, since sometimes the extension | ||
* doesn't reflect the mime type, and may end up getting changed by | ||
* the server, on upload. | ||
* | ||
* @param {string[]} urls The list of URLs | ||
* @return {Record< string, string >} A URL => basename record. | ||
*/ | ||
export function generateUniqueBasenames( urls ) { | ||
const basenames = new Set(); | ||
|
||
return Object.fromEntries( | ||
urls.map( ( url ) => { | ||
// We prefer to match the remote filename, if possible. | ||
const filename = getFilename( url ); | ||
let basename = ''; | ||
|
||
if ( filename ) { | ||
const parts = filename.split( '.' ); | ||
if ( parts.length > 1 ) { | ||
// Assume the last part is the extension. | ||
parts.pop(); | ||
} | ||
basename = parts.join( '.' ); | ||
} | ||
|
||
if ( ! basename ) { | ||
// It looks like we don't have a basename, so let's use a UUID. | ||
basename = uuid(); | ||
} | ||
|
||
if ( basenames.has( basename ) ) { | ||
// Append a UUID to deduplicate the basename. | ||
// The server will try to deduplicate on its own if we don't do this, | ||
// but it may run into a race condition | ||
// (see https://github.com/WordPress/gutenberg/issues/64899). | ||
// Deduplicating the filenames before uploading is safer. | ||
basename = `${ basename }-${ uuid() }`; | ||
} | ||
|
||
basenames.add( basename ); | ||
|
||
return [ url, basename ]; | ||
} ) | ||
); | ||
} | ||
|
||
/** | ||
* Fetch a list of URLs, turning those into promises for files with | ||
* unique filenames. | ||
* | ||
* @param {string[]} urls The list of URLs | ||
* @return {Record< string, Promise< File > >} A URL => File promise record. | ||
*/ | ||
export function fetchMedia( urls ) { | ||
return Object.fromEntries( | ||
Object.entries( generateUniqueBasenames( urls ) ).map( | ||
( [ url, basename ] ) => { | ||
const filePromise = window | ||
.fetch( url.includes( '?' ) ? url : url + '?' ) | ||
.then( ( response ) => response.blob() ) | ||
.then( ( blob ) => { | ||
// The server will reject the upload if it doesn't have an extension, | ||
// even though it'll rewrite the file name to match the mime type. | ||
// Here we provide it with a safe extension to get it past that check. | ||
return new File( [ blob ], `${ basename }.png`, { | ||
type: blob.type, | ||
} ); | ||
} ); | ||
|
||
return [ url, filePromise ]; | ||
} | ||
) | ||
); | ||
} |
Oops, something went wrong.