Pruebas con MinIO y ASP.NET Core.
docker run -d `
--name minio `
-p 9000:9000 `
-p 9001:9001 `
-e MINIO_ROOT_USER=minioadmin `
-e MINIO_ROOT_PASSWORD=minioadmin `
-v /minio/data:/data `
quay.io/minio/minio server /data --console-address ":9001"Explicación de parámetros:
-d: Ejecuta el contenedor en modo detached (en segundo plano)--name minio: Asigna el nombre "minio" al contenedor-p 9000:9000: Mapea el puerto 9000 del contenedor al puerto 9000 del host (API de MinIO)-p 9001:9001: Mapea el puerto 9001 del contenedor al puerto 9001 del host (Consola web)-e MINIO_ROOT_USER=minioadmin: Establece el usuario administrador-e MINIO_ROOT_PASSWORD=minioadmin: Establece la contraseña del administrador-v /minio/data:/data: Monta un volumen para persistir los datosquay.io/minio/minio: Imagen oficial de MinIOserver /data: Inicia MinIO como servidor de almacenamiento usando/datacomo directorio de almacenamiento--console-address ":9001": Especifica la dirección de la consola web de administración
- Console: http://localhost:9001 (
minioadmin/minioadmin) - Crear bucket
mybucket - Subir archivos de prueba
cd minIO-example.API
dotnet run- Swagger: http://localhost:5135/swagger
| Endpoint | Qué hace |
|---|---|
GET /api/example/presigned-url |
URL para descargar archivo |
GET /api/example/list-objects |
Listar archivos del bucket |
POST /api/example/upload |
Subir archivo |
- Swagger UI: http://localhost:5135/swagger
- Archivo .http: Usar
minIO-example.API.httpen VS Code
docker restart minio # Reiniciar
docker logs minio # Ver logs
docker stop minio # Detener- Swagger UI: http://localhost:5135/swagger
- Archivo .http:
minIO-example.API.httpen VS Code - Usuario:
minioadmin - Contraseña:
minioadmin
- Ve a http://localhost:9001
- Inicia sesión con
minioadmin/minioadmin - Crea un bucket llamado
mybucket - Sube algunos archivos de prueba (opcional)
cd minIO-example.API
dotnet runLa API estará disponible en:
- API: http://localhost:5135
- Swagger UI: http://localhost:5135/swagger
| Método | Endpoint | Descripción |
|---|---|---|
GET |
/api/ImageDownload/url |
Genera URL presignada (1 hora) con verificación |
GET |
/api/ImageDownload/url-custom-expiry |
URL presignada con expiración personalizada |
GET |
/api/ImageDownload/secure-url |
URL segura + metadatos (solo si existe) |
GET |
/api/ImageDownload/validate |
Validación completa con detalles |
GET |
/api/ImageDownload/exists |
Verifica si existe una imagen (true/false) |
GET |
/api/ImageDownload/list |
Lista todas las imágenes en un bucket |
GET |
/api/ImageDownload/bucket-exists |
Verifica si existe un bucket |
GET |
/api/ImageDownload/info |
Obtiene metadatos de una imagen específica |
| Método | Endpoint | Descripción |
|---|---|---|
POST |
/api/ImageUpload/upload |
Sube imagen con nombre original |
POST |
/api/ImageUpload/upload-custom-name |
Sube imagen con nombre personalizado |
POST |
/api/ImageUpload/upload-with-folder |
Sube imagen organizándola en carpetas |
GET |
/api/ImageUpload/upload-url |
Genera URL presignada para upload |
GET /api/ImageDownload/secure-url?bucketID=mybucket&imageName=myimage.jpg&expirySeconds=3600Respuesta si existe:
{
"url": "https://localhost:9000/mybucket/myimage.jpg?X-Amz-Algorithm=...",
"expiresIn": 3600,
"expiresAt": "2025-10-27T15:30:00Z",
"imageInfo": {
"name": "myimage.jpg",
"size": 1024768,
"sizeFormatted": "1.0 MB",
"contentType": "image/jpeg",
"lastModified": "2025-10-27T14:30:00Z",
"eTag": "abc123..."
},
"bucketName": "mybucket",
"status": "Success"
}Respuesta si no existe:
HTTP 404 - "Image 'myimage.jpg' does not exist in bucket 'mybucket'"GET /api/ImageDownload/validate?bucketID=mybucket&imageName=myimage.jpgRespuesta detallada:
{
"exists": false,
"reason": "ImageNotFound",
"message": "Image 'myimage.jpg' does not exist in bucket 'mybucket'",
"bucketName": "mybucket",
"imageName": "myimage.jpg",
"isImageExtension": true
}# 1. Validar imagen antes de generar URL
curl "http://localhost:5135/api/ImageDownload/validate?bucketID=mybucket&imageName=myimage.jpg"
# 2. Obtener URL segura (solo si existe)
curl "http://localhost:5135/api/ImageDownload/secure-url?bucketID=mybucket&imageName=myimage.jpg&expirySeconds=7200"
# 3. Verificación rápida de existencia
curl "http://localhost:5135/api/ImageDownload/exists?bucketID=mybucket&imageName=myimage.jpg"
# 4. Listar todas las imágenes en un bucket
curl "http://localhost:5135/api/ImageDownload/list?bucketID=mybucket"# Subir imagen con nombre original
curl -X POST "http://localhost:5135/api/ImageUpload/upload?bucketID=mybucket" \
-F "file=@myimage.jpg"
# Subir con nombre personalizado
curl -X POST "http://localhost:5135/api/ImageUpload/upload-custom-name?bucketID=mybucket&customName=custom_image" \
-F "file=@myimage.jpg"
# Subir organizando en carpetas
curl -X POST "http://localhost:5135/api/ImageUpload/upload-with-folder?bucketID=mybucket&folder=photos/2025" \
-F "file=@myimage.jpg"# URL presignada con verificación automática
curl "http://localhost:5135/api/ImageDownload/url?bucketID=mybucket&imageName=myimage.jpg"
# URL presignada sin verificación (comportamiento anterior)
curl "http://localhost:5135/api/ImageDownload/url?bucketID=mybucket&imageName=myimage.jpg&skipExistenceCheck=true"
# URL con expiración personalizada y verificación
curl "http://localhost:5135/api/ImageDownload/url-custom-expiry?bucketID=mybucket&imageName=myimage.jpg&expirySeconds=1800"Abre minIO-example.API.http en VS Code y usa los ejemplos incluidos.
Ve a http://localhost:5135/swagger para una interfaz interactiva.
Puedes sobrescribir la configuración usando variables de entorno:
export MINIO_ENDPOINT=localhost:9000
export MINIO_ACCESS_KEY=minioadmin
export MINIO_SECRET_KEY=minioadmin{
"MinIO": {
"Endpoint": "localhost:9000",
"AccessKey": "minioadmin",
"SecretKey": "minioadmin",
"UseSSL": false
}
}# Ver logs de MinIO
docker logs minio
# Detener MinIO
docker stop minio
# Reiniciar MinIO
docker restart minio
# Eliminar contenedor (¡cuidado! se pierden los datos)
docker rm -f minio
# Ver contenedores en ejecución
docker psminIO-example/
├── minIO-example.API/
│ ├── Controllers/
│ │ ├── ImageDownloadController.cs # 🔽 Descargar imágenes (URLs seguras)
│ │ └── ImageUploadController.cs # 📤 Subir imágenes
│ ├── Program.cs # Configuración de la app
│ ├── minIO-example.API.http # Ejemplos de requests
│ └── minIO-example.API.csproj
└── README.md # Este archivo
- Verificación automática de existencia antes de generar URLs
- Respuestas
404 Not Founden lugar de URLs inválidas - Metadatos incluidos en respuestas de URLs seguras
- Endpoint
/validatecon información detallada - Verificación de buckets y objetos por separado
- Información sobre tipo de archivo y extensiones
- Soporte para formatos: JPG, JPEG, PNG, GIF, BMP, WEBP
- Organización en carpetas
- Nombres personalizados para archivos
- Información de tamaño formateada (KB, MB, GB)
- Endpoints existentes mantienen compatibilidad
- Parámetro opcional para omitir verificaciones
- Migración gradual sin romper funcionalidad existente
- ASP.NET Core 9.0 - Framework web
- MinIO .NET Client - Cliente oficial de MinIO
- Swagger/OpenAPI - Documentación de API
- Docker - Contenedor para MinIO
minioadmin/minioadmin) son solo para desarrollo.
Para producción:
- Cambia las credenciales
- Habilita HTTPS
- Configura políticas de acceso apropiadas
- Usa variables de entorno para secrets
- Verifica que el contenedor esté ejecutándose:
docker ps - Verifica los puertos:
netstat -tulpn | grep :9000
- Asegúrate de que
WithSSL(false)esté configurado en desarrollo - Para producción, configura certificados apropiados
- Crea el bucket desde MinIO Console (http://localhost:9001)
- Usa
/bucket-existspara verificar antes de usar
- Usa
/validatepara diagnóstico completo - Usa
/listpara ver qué imágenes están disponibles - Verifica extensiones válidas: JPG, JPEG, PNG, GIF, BMP, WEBP