using MongoDB.Bson; using MongoDB.Driver; using MongoDB.Driver.GridFS; namespace BCards.Web.Services; public class GridFSDocumentStorage : IDocumentStorageService { private const int MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB private static readonly string[] ALLOWED_TYPES = { "application/pdf" }; private readonly GridFSBucket _gridFS; private readonly ILogger _logger; public GridFSDocumentStorage(IMongoDatabase database, ILogger logger) { _gridFS = new GridFSBucket(database, new GridFSBucketOptions { BucketName = "page_documents" }); _logger = logger; } public async Task SaveDocumentAsync(byte[] documentBytes, string fileName, string contentType) { if (documentBytes == null || documentBytes.Length == 0) throw new ArgumentException("Documento inválido."); if (documentBytes.Length > MAX_FILE_SIZE) throw new ArgumentException($"Arquivo muito grande. Tamanho máximo permitido: {MAX_FILE_SIZE / (1024 * 1024)}MB."); if (!ALLOWED_TYPES.Contains(contentType.ToLower())) throw new ArgumentException("Tipo de arquivo não suportado. Envie um PDF."); var uniqueFileName = $"document_{DateTime.UtcNow:yyyyMMdd_HHmmss}_{Guid.NewGuid():N}.pdf"; var options = new GridFSUploadOptions { Metadata = new BsonDocument { { "originalFileName", fileName }, { "contentType", contentType }, { "uploadDate", DateTime.UtcNow }, { "size", documentBytes.Length } } }; var fileId = await _gridFS.UploadFromBytesAsync(uniqueFileName, documentBytes, options); _logger.LogInformation("PDF salvo no GridFS: {FileId}", fileId); return fileId.ToString(); } public async Task GetDocumentAsync(string documentId) { if (!ObjectId.TryParse(documentId, out var objectId)) return null; try { return await _gridFS.DownloadAsBytesAsync(objectId); } catch (GridFSFileNotFoundException) { return null; } } public async Task DeleteDocumentAsync(string documentId) { if (!ObjectId.TryParse(documentId, out var objectId)) return false; try { await _gridFS.DeleteAsync(objectId); return true; } catch (GridFSFileNotFoundException) { return false; } } public async Task DocumentExistsAsync(string documentId) { if (!ObjectId.TryParse(documentId, out var objectId)) return false; var filter = Builders.Filter.Eq("_id", objectId); var fileInfo = await _gridFS.Find(filter).FirstOrDefaultAsync(); return fileInfo != null; } }