aws s3 upload and get apis

This commit is contained in:
Chetan Bedi 2025-06-19 16:41:45 +05:30
parent 804f5b2583
commit 89ff6d27d4
7 changed files with 1995 additions and 8 deletions

View file

@ -20,3 +20,10 @@ ACCESS_TOKEN_EXPIRY=
SUPABASE_URL= SUPABASE_URL=
SUPABASE_KEY= SUPABASE_KEY=
DATABASE_URL= DATABASE_URL=
# aws s3 creds
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION=
AWS_S3_BUCKET=

1887
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -13,18 +13,22 @@
"license": "ISC", "license": "ISC",
"description": "", "description": "",
"dependencies": { "dependencies": {
"@aws-sdk/client-s3": "^3.832.0",
"@aws-sdk/s3-request-presigner": "^3.832.0",
"bcrypt": "^6.0.0", "bcrypt": "^6.0.0",
"dotenv": "^16.5.0", "dotenv": "^16.5.0",
"express": "^5.1.0", "express": "^5.1.0",
"joi": "^17.13.3", "joi": "^17.13.3",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"multer": "^2.0.1",
"pg": "^8.16.0", "pg": "^8.16.0",
"pg-hstore": "^2.3.4", "pg-hstore": "^2.3.4",
"postgres": "^3.4.7", "postgres": "^3.4.7",
"sequelize": "^6.37.7", "sequelize": "^6.37.7",
"swagger-jsdoc": "^6.2.8", "swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.1", "swagger-ui-express": "^5.0.1",
"twilio": "^5.7.1" "twilio": "^5.7.1",
"uuid": "^11.1.0"
}, },
"devDependencies": { "devDependencies": {
"nodemon": "^3.1.10" "nodemon": "^3.1.10"

View file

@ -1,4 +1,5 @@
import User from '../models/user.js'; import User from '../models/user.js';
import { uploadFile, getSignedFileUrl } from "../service/s3.service.js";
// UPDATE USER // UPDATE USER
const updateUser = async (req, res) => { const updateUser = async (req, res) => {
@ -47,9 +48,48 @@ const deleteUser = async (req, res) => {
res.json({ message: 'User deleted' }); res.json({ message: 'User deleted' });
}; };
/**
* Upload file to S3 and return fileKey
*/
const uploadS3File = async (req, res) => {
try {
console.log("Received file:", req.file?.originalname);
if (!req.file) {
return res.status(400).json({ error: "No file provided" });
}
const fileKey = await uploadFile(req.file);
res.json({ message: "File uploaded successfully", fileKey });
} catch (err) {
console.error("S3 upload error:", err);
res.status(500).json({ error: err.message });
}
};
/**
* Generate a signed URL for S3 file
*/
const getS3SignedUrl = async (req, res) => {
try {
const { key } = req.params;
if (!key) {
return res.status(400).json({ error: "File key is required" });
}
const url = await getSignedFileUrl(key);
res.json({ url });
} catch (err) {
console.error("S3 signed URL error:", err);
res.status(500).json({ error: err.message });
}
};
export default { export default {
updateUser, updateUser,
getAllUsers, getAllUsers,
getUserById, getUserById,
deleteUser, deleteUser,
uploadS3File,
getS3SignedUrl
}; };

View file

@ -4,7 +4,8 @@ import userController from "../controllers/user.controller.js";
import validate from "../middleware/validate.js"; import validate from "../middleware/validate.js";
import { updateUserSchema } from "../validators/user.validator.js"; import { updateUserSchema } from "../validators/user.validator.js";
import verifyToken from "../middleware/authenticate.js"; import verifyToken from "../middleware/authenticate.js";
import multer from "multer";
const upload = multer(); // memory storage
router.put( router.put(
"/update-user", "/update-user",
@ -13,5 +14,12 @@ router.put(
userController.updateUser userController.updateUser
); );
router.post("/upload", upload.single("file"), userController.uploadS3File);
router.get(
"/get-upload/:key",
userController.getS3SignedUrl
);
export default router; export default router;

40
src/service/s3.service.js Normal file
View file

@ -0,0 +1,40 @@
import { S3Client, PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { v4 as uuidv4 } from "uuid";
import s3Client from "../utils/s3Client.js";
const bucketName = process.env.AWS_S3_BUCKET;
export const uploadFile = async (file) => {
if (!file || !file.buffer) {
throw new Error("Invalid file data");
}
const fileKey = `${uuidv4()}-${file.originalname}`;
const command = new PutObjectCommand({
Bucket: bucketName,
Key: fileKey,
Body: file.buffer,
ContentType: file.mimetype,
});
await s3Client.send(command);
return fileKey;
};
export const getSignedFileUrl = async (fileKey, expiresIn = 3600) => {
if (!fileKey) {
throw new Error("File key is required");
}
const command = new GetObjectCommand({
Bucket: bucketName,
Key: fileKey,
});
const signedUrl = await getSignedUrl(s3Client, command, { expiresIn });
return signedUrl;
};

11
src/utils/s3Client.js Normal file
View file

@ -0,0 +1,11 @@
import { S3Client } from "@aws-sdk/client-s3";
const s3Client = new S3Client({
region: process.env.AWS_REGION,
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
},
});
export default s3Client;