/** * Copyright (c) 2026 Niolla * All rights reserved. * * This source code is proprietary and confidential. * Unauthorized copying, modification, distribution, or use * of this file, via any medium, is strictly prohibited. */ // app/utils/s3Upload.util.js const { PutObjectCommand, GetObjectCommand } = require("@aws-sdk/client-s3"); const { getSignedUrl } = require("@aws-sdk/s3-request-presigner"); const s3 = require("../config/s3.config"); const { v4: uuidv4 } = require("uuid"); const path = require("path"); const redis = require("../config/redisClient"); const { log } = require("./consoleLog.utill"); // Upload + return key (BEST PRACTICE) const uploadToS3 = async (file, usedFor) => { try { const fileExtension = path.extname(file.originalname); const fileName = `${uuidv4()}${fileExtension}`; let key = `uploads/${fileName}`; if (usedFor === "asset") { key = `assets/${fileName}`; } log("Uploading file to S3 with key:", key); const params = { Bucket: process.env.AWS_S3_BUCKET_NAME, Key: key, Body: file.buffer, ContentType: file.mimetype, }; await s3.send(new PutObjectCommand(params)); // Return KEY (not URL) return key; } catch (error) { log("S3 Upload Error:", error); throw new Error("File upload failed"); } }; // Generate signed URL with Redis caching const getSignedFileUrl = async (key) => { try { const cacheKey = `s3:url:${key}`; // 1. Check cache const cachedUrl = await redis.get(cacheKey); if (cachedUrl) { log("⚡ Cache HIT - returning signed URL from Redis"); return cachedUrl; } log("🐢 Cache MISS - generating new signed URL"); // 2. Generate signed URL const command = new GetObjectCommand({ Bucket: process.env.AWS_S3_BUCKET_NAME, Key: key, }); const signedUrl = await getSignedUrl(s3, command, { expiresIn: 3600, // 1 hour }); // 3. Store in Redis (TTL: 55 minutes) await redis.set(cacheKey, signedUrl, "EX", 3300); return signedUrl; } catch (error) { log("Signed URL Error:", error); throw new Error("Failed to generate file URL"); } }; module.exports = { uploadToS3, getSignedFileUrl, };