Skip to content

Commit

Permalink
Small bug fix to prevent restarting upload if getUploadParams isn't d…
Browse files Browse the repository at this point in the history
…efined; adds S3 uploader example to README
  • Loading branch information
kylebebak committed Oct 30, 2018
1 parent 8486c6d commit 9560f6d
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 3 deletions.
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,36 @@ If you use the component injection API, you'll want to know which props are pass


## Example: S3 Uploader
Let's say you want to upload a file to one of your S3 buckets. You have an API service class, `myApiService`, that can send requests to your API to get file upload params.

Maybe your API [uses Boto to do this](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.generate_presigned_post). If a request is successful, it returns `{ fields, uploadUrl, fileUrl }`, else it returns `{}`. A successful response looks like this:

~~~json
{
"fields": {
"AWSAccessKeyId": "AKIAJSQUO7ORWYVCSV6Q",
"acl": "public-read",
"key": "files/89789486-d94a-4251-a42d-18af752ab7d2-test.txt",
"policy": "eyJleHBpcmF0aW9uIjogIjIwMTgtMTAtMzBUMjM6MTk6NDdaIiwgImNvbmRpdGlvbnMiOiBbeyJhY2wiOiAicHVibGljLXJlYWQifSwgWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsIDEwLCAzMTQ1NzI4MF0sIHsiYnVja2V0IjogImJlYW10ZWNoLWZpbGUifSwgeyJrZXkiOiAiY29tcGFueS8zLzg5Nzg5NDg2LWQ5NGEtNDI1MS1hNDJkLTE4YWY3NTJhYjdkMi10ZXN0LnR4dCJ9XX0=",
"signature": "L7r3KBtyOXjUKy31g42JTYb1sio="
},
"fullUrl": "https://my-bucket.s3.amazonaws.com/files/89789486-d94a-4251-a42d-18af752ab7d2-test.txt",
"uploadUrl": "https://my-bucket.s3.amazonaws.com/"
}
~~~

Fields has everything you need to authenticate with your S3 bucket, but you need to add them to the request sent by RDU. It turns out __this is ridiculously easy__.

~~~js
const getUploadParams = async ({ meta: { name } }) => {
const { fields, uploadUrl, fileUrl } = await myApiService.getPresignedUploadParams(name)
return { fields, meta: { fileUrl }, url: uploadUrl }
}
~~~

That's it. If `myApiService.getPresignedUploadParams` is successful, you merge `fileUrl` into your file's meta so you can use it later, and you return `uploadUrl` as `url`. RDU will take care of the rest, including appending the fields to the the `formData` instance used in the `XMLHttpRequest`.

If `myApiService.getPresignedUploadParams` fails, `uploadUrl`, and hence `url`, are undefined. RDU abandons the upload and changes the file's status to `'error_upload_params'`. At this point you might show the user an error message, and the user might remove the file or restart the upload.


## Thanks
Expand Down
11 changes: 11 additions & 0 deletions example/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ const styles = {
backgroundColor: '#F6F8FA',
border: '2px solid #3DC59F',
},
input: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
cursor: 'pointer',
},
}

const App = () => {
Expand All @@ -32,6 +40,9 @@ const App = () => {
onSubmit={handleSubmit}
maxSizeBytes={1024 * 1024 * 1000}
styles={styles}
fileInputText=""
fileInputWithFilesText=""
instructions={<span className="dzu-largeText">Drop Or Pick Files</span>}
/>
)
}
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-dropzone-uploader",
"version": "1.5.0",
"version": "1.5.1",
"author": "Kyle Bebak <kylebebak@gmail.com>",
"description": "React file dropzone and uploader: fully customizable, progress indicators, upload cancellation and restart, zero deps",
"main": "./dist/react-dropzone-uploader.js",
Expand All @@ -9,6 +9,8 @@
"react",
"react-component",
"file",
"HTML5",
"input",
"dropzone",
"uploader",
"progress",
Expand Down
3 changes: 2 additions & 1 deletion src/Dropzone.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,12 @@ class Dropzone extends React.Component {
}

handleRestart = (fileWithMeta) => {
this.uploadFile(fileWithMeta)
if (!this.props.getUploadParams) return
fileWithMeta.meta.status = 'uploading'
this.handleChangeStatus(fileWithMeta)
this.forceUpdate()
if (this.props.onRestart) this.props.onRestart(fileWithMeta)
this.uploadFile(fileWithMeta)
}

// expects an array of File objects
Expand Down
3 changes: 3 additions & 0 deletions src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
align-items: center;
justify-content: center;
height: 100%;
position: relative;
}

.dzu-contentWithFiles {
padding: 3% 5%;
position: relative;
}

.dzu-largeText {
Expand Down Expand Up @@ -85,6 +87,7 @@
height: 70px;
width: auto;
max-width: 140px;
z-index: 1;
}

.dzu-submitButtonContainer {
Expand Down
2 changes: 1 addition & 1 deletion src/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const formatBytes = (b) => {
const units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
const units = ['bytes', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
let l = 0
let n = b

Expand Down

0 comments on commit 9560f6d

Please sign in to comment.