BCards/src/BCards.Web/Services/GridFSDocumentStorage.cs

94 lines
2.9 KiB
C#

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<GridFSDocumentStorage> _logger;
public GridFSDocumentStorage(IMongoDatabase database, ILogger<GridFSDocumentStorage> logger)
{
_gridFS = new GridFSBucket(database, new GridFSBucketOptions
{
BucketName = "page_documents"
});
_logger = logger;
}
public async Task<string> 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<byte[]?> 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<bool> 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<bool> DocumentExistsAsync(string documentId)
{
if (!ObjectId.TryParse(documentId, out var objectId))
return false;
var filter = Builders<GridFSFileInfo>.Filter.Eq("_id", objectId);
var fileInfo = await _gridFS.Find(filter).FirstOrDefaultAsync();
return fileInfo != null;
}
}