useUpload
A react hook to upload files to any cloud service using presigned urls gotten through a REST or Graphql API
github.com/ernestognw/use-uploadGetting started
Installation
With yarn:
yarn add use-upload
With npm:
npm install --save use-upload
Usage
You will need an API endpoint that returns you a presigned URL from the storage service you are using. If you don't know what a presigned URL is, please go to the 'How to use' section down below and you'll learn more
Once you have a valid endpoint, just import accordingly:
import { useRestUpload } from 'use-upload'
useUpload hook returns an object with 4 attributes, described as follows:
upload: () => String - Function to upload the file. It returns a string containing the final URL
uploading: Boolean - Flag to show whether the file is being uploaded or not
progress: Number - Progress of uploading from 0 to 100
reset: () => void - Function to reset the progress
You can use them this way:
const MyComponent = () => {
const {
upload,
uploading,
progress,
reset
} = useRestUpload(
'<YOUR-ENDPOINT>',
{ ...config }
)
const handleUpload = () => {
// Config is equivalent to client.query(_, config)
// See: https://github.com/axios/axios#request-config
const finalUrl = await upload(file, config);
}
return (
...
)
}
For more info you can refer to the 'API Reference' section
Examples
Working example:
0%
Code:
import React, { useState } from 'react';
import { useRestUpload } from 'use-upload';
const Rest = () => {
const [url, setUrl] = useState('');
const [message, setMessage] = useState('');
const { upload, progress, uploading, reset } = useRestUpload(
'http://use-upload.free.beeceptor.com/rest/signFileUrl'
);
const onFileChange = async (event) => {
const [file] = event.target.files;
if (file.size > 1000000) {
setMessage('Sorry, but beeceptor API mock only works with files under 1 MB');
return;
}
const fileUrl = await upload(file, { body: { filePath: file.name, fileType: file.type } });
setUrl(fileUrl);
};
return (
<>
{uploading && <span>uploading...</span>}
<input max-size="1024" disabled={uploading} onChange={onFileChange} type="file" />
<br />
<progress max="100" value={progress} />
<span>{progress}%</span>
{progress === 100 && !uploading && (
<>
<p>url: {url}</p>
<button type="button" onClick={reset}>
Reset
</button>
</>
)}
{message && <p>{message}</p>}
</>
);
};
export default Rest;
How to use
In order to use this hook, you must need to create an API endpoint to retrieve a presigned url. These are the most common cloud storage services you can use with this feature:
This is an example of how to create an s3 instance using aws-sdk
in NodeJS:
AWS S3 Setup
import AWS from 'aws-sdk';
AWS.config.update({
region: '<YOUR-REGION>', // Put your aws region here
accessKeyId: '<YOUR-ACCESS-KEY-ID>',
secretAccessKey: '<YOUR-SECRET-ACCESS-KEY>'
});
const s3 = new AWS.S3();
export default s3;
Here's an example of how to generate a pre-signed URL using AWS on both types of APIs on NodeJS
Note that these are just examples
The endpoints are the ideal use case that fits with the hook defaults, but they're also configurables depending on the case
Express endpoint
import s3 from 'path/to/s3/file';
import express from 'express';
const app = express();
app.get('/<YOUR-ENDPOINT>', (req, res) => {
const { filePath, fileType } = req;
const signedUrl = await s3.getSignedUrlPromise('putObject', {
Bucket: '<YOUR-S3-BUCKET>',
Key: filePath,
Expires: 500, // To prevent future unauthorized uses of URL
ContentType: fileType,
ACL: 'public-read'
});
res.send({
signedUrl,
fileUrl: signedUrl.split(
// After file path, there is always this param
// which is assumed constant.
// This split will left the final file URL
'?X-Amz-Algorithm='
)[0]
});
})
Once you have the API endpoint working endpoint, then, you can use any of the examples listed previously
API Reference
useRestUpload(urlEndpoint[, config])
- urlEndpoint: It is the URL where you will request the pre signed URL
- config: Configuration object with the following defaults:
{ // Axios config to the urlEndpoint // See: https://github.com/axios/axios#request-config getSignedUrlOptions: { method: 'get', }, // Axios config to put the file in the signed url // See: https://github.com/axios/axios#request-config uploadFileOptions: { method: 'put', }, // This is the way to specify how to access urlEndpoint response // It is default as a recommended implementation and according // to the examples previously provided resultPath: { fileUrl: 'fileUrl', signedUrl: 'signedUrl', }, }
Recommended urlEndpoint response schema
{
fileUrl: 'final-file-url.com',
signedUrl: 'presigned-file-url.com?withSignatureParams=...',
}
Made by Ernesto GarcĂa