const Minio = require('minio'); const multer = require('multer'); // Configure MinIO Client const minioClient = new Minio.Client({ endPoint: process.env.MINIO_ENDPOINT || 'localhost', port: parseInt(process.env.MINIO_PORT) || 9000, useSSL: process.env.MINIO_USE_SSL === 'true', accessKey: process.env.MINIO_ACCESS_KEY || 'minioadmin', secretKey: process.env.MINIO_SECRET_KEY || 'minioadmin' }); const BUCKET_NAME = process.env.MINIO_BUCKET_NAME || 'curio-media'; // Ensure bucket exists async function initStorage() { try { const exists = await minioClient.bucketExists(BUCKET_NAME); if (!exists) { await minioClient.makeBucket(BUCKET_NAME, 'us-east-1'); console.log(`[Storage] Bucket '${BUCKET_NAME}' created successfully.`); // Set basic public read policy for media const policy = { Version: '2012-10-17', Statement: [ { Action: ['s3:GetObject'], Effect: 'Allow', Principal: '*', Resource: [`arn:aws:s3:::${BUCKET_NAME}/*`], }, ], }; await minioClient.setBucketPolicy(BUCKET_NAME, JSON.stringify(policy)); } else { console.log(`[Storage] Bucket '${BUCKET_NAME}' already exists.`); } } catch (err) { console.error('[Storage] MinIO Init Error:', err.message); } } // Multer in-memory storage for handling multipart form data before streaming to MinIO const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 10 * 1024 * 1024, // 10MB max file size } }); /** * Upload a file buffer to MinIO * @param {string} fileName * @param {Buffer} fileBuffer * @param {string} mimeType * @returns {Promise} Public URL of the uploaded file */ async function uploadFile(fileName, fileBuffer, mimeType) { try { await minioClient.putObject(BUCKET_NAME, fileName, fileBuffer, fileBuffer.length, { 'Content-Type': mimeType }); const protocol = process.env.MINIO_USE_SSL === 'true' ? 'https' : 'http'; const port = process.env.MINIO_PORT ? `:${process.env.MINIO_PORT}` : ''; // If MinIO is accessible publicly, return the direct URL. // For production behind proxy, this might need to be the proxy URL. const publicUrl = process.env.MINIO_PUBLIC_URL ? `${process.env.MINIO_PUBLIC_URL}/${BUCKET_NAME}/${fileName}` : `${protocol}://${process.env.MINIO_ENDPOINT || 'localhost'}${port}/${BUCKET_NAME}/${fileName}`; return publicUrl; } catch (err) { console.error('[Storage] Upload Error:', err); throw err; } } module.exports = { minioClient, upload, initStorage, uploadFile };