27
loading...
This website collects cookies to deliver better user experience
This post originally appeared on my blog here.
.env
file in our project root:S3_BUCKET_NAME=your_bucket_name // e.g my-bucket
S3_ENDPOINT_URL=your_endpoint_url // e.g https://eu.amazons3.com/
S3_ACCESS_KEY=your_access_key
S3_SECRET_KEY=your_secret_access_key
aws-sdk
this is the npm package used for connecting and interacting with an S3 storage. Run the following command to install:npm install aws-sdk
npm install --save-dev @aws-sdk/types
connection.ts
:import * as S3 from 'aws-sdk/clients/s3';
export default function Connect(path: string | null = ''): S3 {
return new S3({
apiVersion: 'latest',
endpoint: `${process.env.S3_ENDPOINT_URL}${path}`,
credentials: {
accessKeyId: process.env.S3_ACCESS_KEY,
secretAccessKey: process.env.S3_SECRET_KEY,
},
});
}
path
parameter. When this is set we can specify the path that we want to upload our file to. For example we may want to upload an image to a subdirectory called images. So we would set the path to 'images'. This path is then appended to the endpoint URL. So as an example our endpoint now becomes https://eu.amazons3.com/images
. If we don't set the path parameter the connection will default to the buckets root.npm i --save-dev @types/multer
.upload.ts
will look like this:import { PutObjectOutput, PutObjectRequest } from 'aws-sdk/clients/s3';
import {AWSError} from 'aws-sdk/lib/error';
import * as S3 from 'aws-sdk/clients/s3';
import Connect from './connection';
export default async function Upload(bucket: string, file: Express.Multer.File, objectName: string, path: string | null = null): Promise<string> {
return new Promise<string>((resolve, reject) => {
const s3: S3 = Connect(path);
const params: PutObjectRequest = { Bucket: bucket, Key: objectName, Body: file.buffer, ACL: 'public-read', ContentType: file.mimetype };
s3.putObject(params, (err: AWSError, data: PutObjectOutput) => {
if (err) reject(err);
resolve(`${process.env.S3_ENDPOINT_URL}${bucket}/${path}/${objectName}`);
});
});
}
Parameters | Description |
---|---|
bucket | This is the name of the bucket you set up with the provider and what we have stored in our environment variable (e.g my-bucket). |
file | This is the actual file that we are uploading. |
objectName | This is the name that we would like to use when we store the file in the cloud. This name should include your file extension. If you are uploading a gif then this should be image.gif as oppose to just image . |
path | (Optional) This is passed straight through to the connection we made previously. So by default it is set to null, which would mean the file is uploaded to the root of the bucket. If you supply 'images' to this parameter then the file you upload will be stored in a subdirectory called images. |
path
parameter.Parameters | Description |
---|---|
Bucket | This is the name of the bucket. We set this using our bucket parameter. |
Key | This is the name that is used when the file is stored in the bucket. We use our objectName parameter here. |
Body | This is the file we are uploading. This option takes a file buffer. So we use our parameter file.buffer
|
ACL | This option is used to specify the access of the file we are uploading. In this example we are using 'public-read' . This means that anyone who has the URL of the file we upload can read it. If you want to read more about the different ACL types then read here. |
ContentType | This is used to tell S3 the type of file we are uploading. It takes in a file mime type. We pass this in using our file parameters file.mimetype . |
https://eu.amazons3.com/my-bucket/images/image.gif
delete.ts
:import {DeleteObjectOutput, DeleteObjectRequest} from 'aws-sdk/clients/s3';
import {AWSError} from 'aws-sdk/lib/error';
import * as S3 from 'aws-sdk/clients/s3';
import Connect from './connection';
export default async function Delete(bucket: string, objectName: string, path: string | null = null): Promise<DeleteObjectOutput> {
return new Promise<DeleteObjectOutput>((resolve, reject) => {
const s3: S3 = Connect(path);
const params: DeleteObjectRequest = { Bucket: bucket, Key: objectName };
s3.deleteObject(params, (err: AWSError, data: DeleteObjectOutput) => {
if (err) reject(err);
resolve(data);
});
});
}
Parameters | Description |
---|---|
bucket | The name of our bucket we created with the provider and stored in the environment variables. |
objectName | The name that we used when storing the object. E.g image.gif
|
path | The path to the object. E.g 'images' would delete the object with the objectName supplied inside the images subdirectory. If null this defaults to the root of the bucket. |
Bucket
and Key
options using our functions parameters.deleteObject
method on the client, passing in our request parameters and defining a callback. Just like before we check if the callback has errored and reject the promise if an error occurs.deleteObject
response.app.post(
'/upload',
multer().single('formFile'),
async (req, res) => {
if(!req.file) res.status(400).send('Bad Request: No file was uploaded');
// If you want to retain the original filename and extension just use originalname like below
// const filename: string = req.file.originalname;
const fileExtension: string = req.file.originalname.split('.').pop();
const filename: string = `my-custom-filename.${fileExtension}`;
const url: string = await Upload(process.env.S3_BUCKET_NAME, req.file, filename, 'images/logo');
res.status(201).send(url);
});
formFile
. This key should be paired with a file. The middleware then attaches the file object to the request under the property file
.my-custom-filename.gif
.images/logo
.