UNPKG

@modbox/s3-uploads-client

Version:
161 lines (134 loc) 7.83 kB
# `@modbox/s3-uploads-client` > Note: This is the client-side package for the s3-upload module, see [@modbox/s3-upload-server](https://www.npmjs.com/package/@modbox/s3-uploads-server) for the server package. # s3-upload approach This lib abstracts away the complexity of presigned requests uploads to an S3-compatible object storage service.\ Based on two (backend and frontend) simple configurations that define onse or several upload types, for each of which your can : - Choose between `simple` or `multipart` upload - Whitelist a set of allowed mimetypes and sizes - Allow or forbid file replacement - Define a naming strategy and key conflict handler - Define a post-upload renaming strategy (e.g. your file should be `${postId}/${filename}` and the `postId` is not generated until the upload is successful and the resource created in database) Written in typescript with DX in mind. # Client-side usage ### _Setup and config_ --- `utils/upload.ts` ```ts import { setupUploadModule, InitiatedUpload, MultipartUploadChunk, PresignedRequestInfo, } from '@modbox/s3-uploads-client' // Define your upload types, you can use an enum, // this must be the same as declared in your backend export enum UploadType { Avatar = 'Avatar', CommunityPost = 'CommunityPost', ResourceFiles = 'ResourceFiles', } export const uploadModule = setupUploadModule({ maxConcurrentUploads: 2, uploads: { [UploadType.Avatar]: { initiate: (files: File[]): Promise<InitiatedUpload[]> => { // Do something here to communicate with your backend (see @modbox/s3-upload-server) // and fetch presigned requests data (i.e. InitiatedUploads) // for the files received as parameter. // Return the backend response. }, }, [UploadType.CommunityPost]: { initiate: (files: File[]): Promise<InitiatedUpload[]> => { // Do something here to communicate with your backend (see @modbox/s3-upload-server) // and fetch presigned requests data (i.e. InitiatedUploads) // for the files received as parameter. // Return the backend response. }, getPartRequest: async ( chunk: MultipartUploadChunk, ): Promise<PresignedRequestInfo> => { // Do something here to communicate with your backend and return // the presigned request infos for part upload }, }, [UploadType.ResourceFiles]: { initiate: (files: File[]): Promise<InitiatedUpload[]> => { // Do something here to communicate with your backend (see @modbox/s3-upload-server) // and fetch presigned requests data (i.e. InitiatedUploads) // for the files received as parameter. // Return the backend response. }, getPartRequest: async ( chunk: MultipartUploadChunk, ): Promise<PresignedRequestInfo> => { // Do something here to communicate with your backend and return // the presigned request infos for part upload }, }, }, }) ``` `components/page.tsx` ```ts import React, { useState } from 'react' import { CancellableUpload, S3Object } from '@modbox/s3-uploads-client' import { ProgressBar } from 'components/ProgressBar' import { uploadModule } from 'utils/upload' const PageComponent = () => { const [uploadProgress, setUploadProgress] = useState<{ total: number completed: number }>({ total: 1, completed: 0 }) const [uploads, setUploads] = useState<File[]>([]) const startUpload = () => { const pendingUploads = await uploadModule.CommunityPost.uploadMany( uploads, { onProgress: ({ completedChunksCount, totalChunksCount }) => { setUploadProgress({ completed: completedChunksCount, total: totalChunksCount, }) }, onUploadComplete: (uploadCompleted, originalFile) => { console.log('A file was uploaded') }, onError: (uploadError) => { console.error('Error: ', uploadError) }, }, ) } return ( <div> <ProgressBar progress={uploadProgress} /> <input type="file" multiple onChange={(e) => { const fileList = ( e.target as unknown as { files: FileList } ).files setUploads(toFileArray(fileList)) }} /> <button onClick={() => startUpload()}></button> </div> ) } ``` ### _Configuration object_ --- This is the definition of the config object passed to `setupUploadModule`. | Property | Type | Required | Default | Description | | ------------------------ | ----------------------------------------------------------------- | -------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | maxConcurrentUploads | `number` | false | 2 | The number of concurrent uploads | | uploads | _See below for full breakdown of this object_ | **true** | | This object defines the different upload types as keys and their specific config as value. | | _uploads_.initiate | `(files: File[], ctx: any) => Promise<InitiatedUpload[]>` | **true** | | Handler that perform the network request to get the presigned requests data (i.e. InitiatedUploads) from the backend for a set of files passed as parameters. `ctx` is anything that you which to pass to your handler in order to perform the request. | | _uploads_.complete | `(files: UploadedFile[], ctx: any) => Promise<S3Object[]>` | false | | Handler to perform a request in order to complete an upload. This is not needed as you might want to complete your upload by passing your `UploadedFile`s in the payload of another request depending on your use case. (e.g. Uploads that are part of a forum post could be passed along the post to create). | | _uploads_.getPartRequest | `(upload: MultipartUploadChunk) => Promise<PresignedRequestInfo>` | false | | Handler to fetch the needed presigned request for each part of your multipart upload. Required if your upload is set to `multipart` | ## Notes This lib is still in development and will be considered production-ready when it reach version `1.0.0`. Use at your own risk. Breaking changes might occur before `1.0.0`, so you might want to use strict references in your `package.json` dependencies. After `1.0.0`, semver will be rigorously respected.