Using Express to Upload an Image to S3
File Upload — Express, MongoDB, Multer & S3
This postal service assumes yous take a backend server up and running with Express + MongoDB Atlas and want to extend the functionality by adding the ability to upload files, or in this example, images.
I recently made the error of trying to directly upload images to MongoDB. Later a couple of hours of frustration, I reached out to a friend who pointed me in the right direction: Amazon S3.
Dependancies:
dotenv: Dotenv is a zero-dependency module that loads surroundings variables from a .env file into process.env
aws-sdk: The official AWS SDK for JavaScript, bachelor for browsers and mobile devices, or Node.js backends
multer: Multer is a node.js middleware for handling multipart/form-data, which is primarily used for uploading files. It is written on peak of busboy for maximum efficiency.
multer-s3: Streaming multer storage engine for AWS S3.
npm i --relieve dotenv aws-sdk multer multer-s3 Getting Started:
First, head over to https://aws.amazon.com/s3/ and create an business relationship. Once y'all have setup your business relationship, navigate to the S3 services dashboard so yous tin create a new saucepan. When yous create a new bucket, the proper noun has to be unique and in DNS-compliant format. For example: "{app-name}-profile-pictures" — at that place are no specific settings yous have to gear up to just click 'next' through the setup process.
Once your bucket has been created, click into the bucket then select permissions > CORS configuration and enter the following code to allow for HTTP requests.
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration> Bully. Now we need to get the Admission Key + Secret. To practise that, open your account dropdown and select "My Security Credentials."
Inside the security credentials dashboard, open the "Access Keys" section. In one case there, select "Create New Admission Primal." This will generate and access fundamental and secret for your app. Store the fundamental + hole-and-corner on your estimator, locally, in a notes app.
BE VERY CAREFUL Nearly WHERE YOU PLACE THE Key + SECRET IN YOUR APP. THERE ARE WEB CRAWLERS SCANNING GITHUB REPO'S FOR Admission KEYS + SECRETS. THEY WILL USE YOUR Business relationship AND Stitch A TAB.
Let's jump into your Node / Limited project.
First and foremost, I want to make certain you accept your .env file setup so that your credit card and S3 account are rubber. Inside your server or app file, place the following code:
/server
const cors = crave("cors");
app.use(cors()); Nifty. With that set up up, create a .gitignore file at the root of your project's directory and place .env within it.
At present, create a .env file and place your access central + secret inside information technology:
.env
S3_ACCESS_KEY=accesskeyprovided
S3_ACCESS_SECRET=accesssecretprovided Now we tin get to the fun stuff. Let's create a services directory where we can identify most of the upload logic. Within services, create a file called ImageUpload.js
mkdir services
cd services
touch ImageUpload.js
cd .. First let's load in the dependancies and initialize the S3 connection:
/services/ImageUpload.js
const aws = crave("aws-sdk");
const multer = require("multer");
const multerS3 = require("multer-s3"); const s3 = new aws.S3();
Next, we demand to plug in our admission credentials via our .env variables:
/services/ImageUpload.js
aws.config.update({
secretAccessKey: process.env.S3_ACCESS_SECRET,
accessKeyId: process.env.S3_ACCESS_KEY,
region: "us-east-2",
}); Bully. At present lets'south create a function that validates the file type:
/services/ImageUpload.js
const fileFilter = (req, file, cb) => {
if (file.mimetype === "prototype/jpeg" || file.mimetype === "image/png") {
cb(null, truthful);
} else {
cb(new Error("Invalid file type, just JPEG and PNG is immune!"), false);
}
}; Now we volition setup Multer to process the epitome and send it to the S3 bucket.
/services/ImageUpload.js
const upload = multer({
fileFilter,
storage: multerS3({
acl: "public-read",
s3,
saucepan: {your-bucket-proper noun},
metadata: function (req, file, cb) {
cb(zero, { fieldName: "TESTING_METADATA" });
},
key: function (req, file, cb) {
cb(zilch, Date.now().toString());
},
}),
}); Before setting up the route, make sure you export the upload function. Below is the full code.
/services/ImageUpload.js
const aws = require("aws-sdk");
const multer = require("multer");
const multerS3 = require("multer-s3");const s3 = new aws.S3();
aws.config.update({
secretAccessKey: process.env.S3_SECRET,
accessKeyId: procedure.env.S3_ACCESS_KEY,
region: "united states-e-2",
});
const fileFilter = (req, file, cb) => {
if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") {
cb(null, true);
} else {
cb(new Error("Invalid file type, just JPEG and PNG is allowed!"), faux);
}
};
const upload = multer({
fileFilter,
storage: multerS3({
acl: "public-read",
s3,
bucket: {your-bucket-name},
metadata: role (req, file, cb) {
cb(zippo, { fieldName: "TESTING_METADATA" });
},
key: function (req, file, cb) {
cb(zilch, Date.now().toString());
},
}),
});
module.exports = upload;
For my app, I wanted to extend the functionality by assuasive users to upload a profile picture show. And then, the user volition send a request to the route /users/{id}/add-profile-motion picture. First, the image is uploaded to S3, S3 sends a response which contains the URL to the photograph, we then employ the [:id] params to find the User with Mongo then store the file location on the User'due south document.
/routes/users
const upload = crave("../services/ImageUpload");
const singleUpload = upload.single("prototype");router.mail service("/:id/add together-profile-picture", part (req, res) {
const uid = req.params.id;
singleUpload(req, res, role (err) {
if (err) {
return res.json({
success: faux,
errors: {
championship: "Image Upload Error",
detail: err.message,
error: err,
},
});
}
allow update = { profilePicture: req.file.location };
User.findByIdAndUpdate(uid, update, { new: true })
.then((user) => res.condition(200).json({ success: true, user: user }))
.catch((err) => res.condition(400).json({ success: false, error: err }));
});
});
With the route setup, you can use Postman to test information technology out. Startup your server, caput over to Postman, enter the corresponding route, select grade-data and choose an prototype from your figurer. Make sure that yous ready the key to image and hit send.
If you lot are interested in learning how to upload the prototype from a React frontend, please bank check out my other post:
https://levelup.gitconnected.com/react-uploading-images-a224e0fb4561
Source: https://levelup.gitconnected.com/file-upload-express-mongodb-multer-s3-7fad4dfb3789
0 Response to "Using Express to Upload an Image to S3"
Post a Comment