- Notifications
You must be signed in to change notification settings - Fork 12
Upload New Media File #92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, just one big question to resolve
src/files/manager.ts Outdated
| const mimetype = options?.mimetype || 'application/octet-stream'; | ||
| | ||
| const blob = new Blob([file], { type: mimetype }); | ||
| formData.append('files', blob, filename); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const blob = new Blob([new Uint8Array(file)], { type: mimetype }); Fixes type issue.
However, I'm not sure it will be necessary with my comment above on the method signature
src/files/manager.ts Outdated
| async upload(file: Blob, fileInfo?: FileUpdateData): Promise<MediaUploadResponse>; | ||
| async upload(file: Buffer, options?: FileUploadOptions): Promise<MediaUploadResponse>; | ||
| async upload( | ||
| file: Blob | Buffer, | ||
| optionsOrFileInfo?: FileUploadOptions | FileUpdateData | ||
| ): Promise<MediaUploadResponse> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm concerned about properly typing this without it being confusing. What do you think about something like:
export interface BlobUploadOptions { fileInfo?: FileUpdateData; } export interface BufferUploadOptions { filename: string; mimetype: string; fileInfo?: FileUpdateData; } // ... async upload(file: Blob, options?: BlobUploadOptions): Promise<MediaUploadResponse>; async upload(file: Buffer, options?: BufferUploadOptions): Promise<MediaUploadResponse>; async upload( file: Blob | Buffer, options?: BlobUploadOptions | BufferUploadOptions ): Promise<MediaUploadResponse> { // some type checking to ensure if a Blob is passed in, BlobUploadOptions are passed in, etc // could then split out if(isBuffer) uploadBuffer(file, options); // buffer specific method if(isBlob) uploadBlob(file, options); // blob specific method }There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might be overcomplicating it though; I just would try to avoid having different options interfaces for the two methods, and instead just ensure that filename+metadata are included if required.
It could actually be a lot simpler than I just wrote above, it could be like
if(isBuffer && !hasFilenameAndMetadata) throw new Error("Filename and metadata are required when uploading Buffer data");Now that I think about it, that could work better. What do you think?
Co-authored-by: Ben Irvin <ben.irvin@strapi.io>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's fine now, just one last comment for you to take a look at and then I think we can merge.
| | ||
| return this.uploadBuffer(file, options as BufferUploadOptions, client, url); | ||
| } else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (file instanceof Buffer && typeof Buffer !== 'undefined' && Buffer.isBuffer(file)) { if (!options || !('filename' in options) || !('mimetype' in options)) { throw new Error('Filename and mimetype are required when uploading Buffer data'); } return this.uploadBuffer(file, options, client, url); } else if (file instanceof Blob) { return this.uploadBlob(file, options, client, url); } else { console.warn('Could not determine type of file; attempting upload as Blob'); return this.uploadBlob(file as unknown as Blob, options as BlobUploadOptions, client, url); }Haven't tested it, but maybe something like this just to be sure and help with debugging
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! Tested and LGTM!
| * // Upload with a File object (browser) | ||
| * const fileInput = document.querySelector('input[type="file"]'); | ||
| * const file = fileInput.files[0]; | ||
| * const result = await filesManager.upload(file, { | ||
| * fileInfo: { alternativeText: 'A user uploaded image' } | ||
| * }); | ||
| * | ||
| * // Upload with a Blob | ||
| * import { blobFrom } from 'node-fetch'; | ||
| * const file = await blobFrom('./1.png', 'image/png'); | ||
| * const result = await filesManager.upload(file, { | ||
| * fileInfo: { alternativeText: 'An example image' } | ||
| * }); | ||
| * | ||
| * // Upload with a Buffer (Node.js) - filename and mimetype are required | ||
| * import fs from 'fs'; | ||
| * const buffer = fs.readFileSync('./image.png'); | ||
| * const result = await filesManager.upload(buffer, { | ||
| * filename: 'image.png', | ||
| * mimetype: 'image/png', | ||
| * fileInfo: { alternativeText: 'An example image' } | ||
| * }); | ||
| * | ||
| * console.log(result); // Upload response with file details | ||
| * ``` | ||
| */ | ||
| async upload(file: Blob, options?: BlobUploadOptions): Promise<MediaUploadResponse>; | ||
| async upload(file: Buffer, options: BufferUploadOptions): Promise<MediaUploadResponse>; | ||
| async upload( | ||
| file: Blob | Buffer, | ||
| options?: BlobUploadOptions | BufferUploadOptions | ||
| ): Promise<MediaUploadResponse> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Bassel17 and @maccomaccomaccomacco
Could you add another voice to this method signature in particular? Jamie and I think we've got it, but since changing this would be a breaking change later I want to make sure we're not missing something.
Usage would be those three uses written in the header comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks fine, even if we add new stuff to it later it will just be additions and won't be breaking changes, like uploading maybe multiple files or something like that
What does it do?
Implements the
client.media.upload()method in the Strapi JavaScript Client. This method allows developers to upload a new media file directly to the Strapi Media Library by sending a POST request to the/api/upload/filesendpoint.Why is it needed?
Previously, uploading media files to Strapi required developers to manually construct and send REST API calls.
How to test it?
client.media.uploadFileResponseRelated issue(s)/PR(s)
DX-2040