anexado guardar en minio y cambios generales en la interfaz de osp

This commit is contained in:
2026-02-24 11:00:50 -04:00
parent fed90d9ff1
commit c70e146ce2
22 changed files with 5139 additions and 696 deletions

View File

@@ -0,0 +1,118 @@
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import * as Minio from 'minio';
import { envs } from '../config/envs';
@Injectable()
export class MinioService implements OnModuleInit {
private readonly minioClient: Minio.Client;
private readonly logger = new Logger(MinioService.name);
private readonly bucketName = envs.minio_bucket;
constructor() {
this.minioClient = new Minio.Client({
endPoint: envs.minio_endpoint,
port: envs.minio_port,
useSSL: envs.minio_use_ssl,
accessKey: envs.minio_access_key,
secretKey: envs.minio_secret_key,
});
}
async onModuleInit() {
await this.ensureBucketExists();
}
private async ensureBucketExists() {
// Ejecuta esto siempre al menos una vez para asegurar que sea público
const policy = {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Principal: { AWS: ['*'] },
Action: ['s3:GetObject'],
Resource: [`arn:aws:s3:::${this.bucketName}/*`],
},
],
};
try {
// const bucketExists = await this.minioClient.bucketExists(this.bucketName);
// if (!bucketExists) {
// await this.minioClient.makeBucket(this.bucketName);
// }
await this.minioClient.setBucketPolicy(
this.bucketName,
JSON.stringify(policy),
);
this.logger.log(`Public policy ensured for bucket "${this.bucketName}"`);
} catch (error: any) {
this.logger.error(`Error checking/creating bucket: ${error.message}`);
}
}
async upload(
file: Express.Multer.File,
folder: string = 'general',
): Promise<string> {
const fileName = `${Date.now()}-${Math.round(Math.random() * 1e9)}-${file.originalname.replace(/\s/g, '_')}`;
const objectName = `${folder}/${fileName}`;
try {
await this.minioClient.putObject(
this.bucketName,
objectName,
file.buffer,
file.size,
{
'Content-Type': file.mimetype,
},
);
// Return the URL or the object path.
// Usually, we store the object path and generate a signed URL or use a proxy.
// The user asked for the URL to be stored in the database.
return objectName;
} catch (error: any) {
this.logger.error(`Error uploading file: ${error.message}`);
throw error;
}
}
async getFileUrl(objectName: string): Promise<string> {
try {
// If the bucket is public, we can just return the URL.
// If private, we need a signed URL.
// For simplicity and common use cases in these projects, I'll generate a signed URL with a long expiration
// or assume there is some way to access it.
// But let's use signed URL for 1 week (maximum is 7 days) if needed,
// or just return the object name if the backend handles the serving.
// The user wants the URL stored in the DB.
return await this.minioClient.presignedUrl(
'GET',
this.bucketName,
objectName,
604800,
);
} catch (error: any) {
this.logger.error(`Error getting file URL: ${error.message}`);
throw error;
}
}
getPublicUrl(objectName: string): string {
const protocol = envs.minio_use_ssl ? 'https' : 'http';
return `${protocol}://${envs.minio_endpoint}:${envs.minio_port}/${this.bucketName}/${objectName}`;
}
async delete(objectName: string): Promise<void> {
try {
await this.minioClient.removeObject(this.bucketName, objectName);
this.logger.log(`Object "${objectName}" deleted successfully.`);
} catch (error: any) {
this.logger.error(`Error deleting file: ${error.message}`);
// We don't necessarily want to throw if the file is already gone
}
}
}