first commit
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
using Fitness_core_BE.Interfaces;
|
||||
using Fitness_core_BE.Interfaces.Services;
|
||||
using Fitness_core_BE.Models;
|
||||
using Fitness_core_BE.Infra.UoW;
|
||||
using System.Text.Json;
|
||||
using Fitness_core_BE.Helpers;
|
||||
using Fitness_core_BE.Exceptions;
|
||||
using Fitness_core_BE.DTOs;
|
||||
|
||||
namespace Fitness_core_BE.Services.Document
|
||||
{
|
||||
public class DocumentService : IDocumentService
|
||||
{
|
||||
private readonly IDocumentRepository _docRepository;
|
||||
private readonly IUnitOfWork _uow;
|
||||
|
||||
public DocumentService(IDocumentRepository docRepository, IUnitOfWork uow)
|
||||
{
|
||||
_docRepository = docRepository;
|
||||
_uow = uow;
|
||||
}
|
||||
|
||||
public async Task<object> UploadDocument(object payload, HttpContext httpContext)
|
||||
{
|
||||
await _uow.BeginAsync();
|
||||
try
|
||||
{
|
||||
Guid userId = DataExtractor.GetUserIdFromContext(httpContext);
|
||||
|
||||
var data = DeserializePayload.Deserialize(payload);
|
||||
|
||||
var files = data["document"].EnumerateArray();
|
||||
bool isTicketDoc = data.TryGetValue("IsTicketDoc", out JsonElement isTicketDocElement) && isTicketDocElement.GetBoolean();
|
||||
var uploadResults = new List<object>();
|
||||
Guid? ticketId = null;
|
||||
if (isTicketDoc && data.TryGetValue("TicketId", out JsonElement ticketIdElement))
|
||||
{
|
||||
ticketId = ticketIdElement.GetGuid();
|
||||
}
|
||||
string uploadsRoot = "./desktop";
|
||||
|
||||
|
||||
if (isTicketDoc && ticketId.HasValue)
|
||||
{
|
||||
// uploadsRoot = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "Uploads", userId.ToString(), ticketId.ToString()));
|
||||
uploadsRoot = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "..", "Uploads", userId.ToString(), ticketId.Value.ToString()));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// uploadsRoot = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "Uploads", userId.ToString()));
|
||||
uploadsRoot = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "..", "Uploads", userId.ToString()));
|
||||
}
|
||||
|
||||
if (!Directory.Exists(uploadsRoot))
|
||||
{
|
||||
Directory.CreateDirectory(uploadsRoot);
|
||||
}
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
string lastnum = await _docRepository.GetLastSequnce();
|
||||
string originalFileName = file.GetProperty("FileName").GetString() ?? "document";
|
||||
string extension = Path.GetExtension(originalFileName).ToLowerInvariant();
|
||||
|
||||
string[] allowedExtensions = { ".pdf", ".jpg", ".jpeg", ".png", ".docx", ".mp4", ".mov", ".avi", ".mkv", ".webm", ".3gp" };
|
||||
if (!allowedExtensions.Contains(extension))
|
||||
throw new BadRequestException("File type not allowed.");
|
||||
|
||||
string safeTimestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
|
||||
string filename = $"{lastnum}_{userId}_{safeTimestamp}{extension}";
|
||||
|
||||
string baseFile = file.GetProperty("Base64").GetString();
|
||||
if (baseFile.Contains(","))
|
||||
baseFile = baseFile.Substring(baseFile.IndexOf(",") + 1);
|
||||
byte[] fileBytes = Convert.FromBase64String(baseFile);
|
||||
|
||||
if (fileBytes.Length > 10 * 1024 * 1024)
|
||||
throw new BadRequestException("File too large.");
|
||||
|
||||
string filePath = Path.Combine(uploadsRoot, filename);
|
||||
await File.WriteAllBytesAsync(filePath, fileBytes);
|
||||
|
||||
// Extract FileType from the file element
|
||||
var fileData = new Dictionary<string, JsonElement> { { "FileType", file.GetProperty("FileType") } };
|
||||
int docTypeId = DataExtractor.GetRequiredInt(fileData, "FileType");
|
||||
|
||||
UserDocument documentMeta = new UserDocument { };
|
||||
|
||||
if (isTicketDoc && ticketId.HasValue)
|
||||
{
|
||||
documentMeta = new UserDocument
|
||||
{
|
||||
UserId = userId,
|
||||
DocumentName = originalFileName,
|
||||
DocumentUrl = $"/Uploads/{userId}/{ticketId.Value}/{Uri.EscapeDataString(filename)}",
|
||||
FkDocumentTypeId = docTypeId,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
documentMeta = new UserDocument
|
||||
{
|
||||
UserId = userId,
|
||||
DocumentName = originalFileName,
|
||||
DocumentUrl = $"/Uploads/{userId}/{Uri.EscapeDataString(filename)}",
|
||||
FkDocumentTypeId = docTypeId,
|
||||
};
|
||||
}
|
||||
|
||||
var savedDocument = await _docRepository.UploadDocumentAsync(documentMeta);
|
||||
await _uow.SaveChangesAsync();
|
||||
uploadResults.Add(new
|
||||
{
|
||||
savedDocument.DocumentId,
|
||||
savedDocument.DocumentName,
|
||||
DocumentURL = savedDocument.DocumentUrl
|
||||
});
|
||||
}
|
||||
|
||||
await _uow.CommitAsync();
|
||||
return new { Message = "Documents uploaded successfully.", uploadResults };
|
||||
}
|
||||
catch
|
||||
{
|
||||
await _uow.RollbackAsync();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<object> GetDocumentsByUserId(object payload, HttpContext httpContext)
|
||||
{
|
||||
// TODO: Uncomment for production - Currently using static userId for testing
|
||||
// if (!Guid.TryParse(httpContext.User.FindFirst("UserId")?.Value, out Guid userId))
|
||||
// {
|
||||
// throw new InvalidOperationException("Invalid UserId in token.");
|
||||
// }
|
||||
|
||||
Guid userId = Guid.Parse("5b664468-9ba5-4e6e-b73a-97c9a791c9a0");
|
||||
|
||||
List<UserDocument> docResults = await _docRepository.GetDocumentsByUserId(userId);
|
||||
|
||||
if (docResults == null || docResults.Count == 0)
|
||||
return new List<object>();
|
||||
|
||||
string uploadsRoot = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), ".."));
|
||||
|
||||
var documents = new List<object>();
|
||||
|
||||
foreach (var doc in docResults)
|
||||
{
|
||||
if (string.IsNullOrEmpty(doc.DocumentUrl))
|
||||
continue;
|
||||
|
||||
string relativePath = doc.DocumentUrl.Replace("/", Path.DirectorySeparatorChar.ToString());
|
||||
Console.WriteLine("Relative Path: " + relativePath);
|
||||
|
||||
string filePath = uploadsRoot + relativePath;
|
||||
Console.WriteLine("File Path: " + filePath);
|
||||
|
||||
if (!File.Exists(filePath))
|
||||
continue; // Skip missing files safely
|
||||
|
||||
byte[] fileBytes = await File.ReadAllBytesAsync(filePath);
|
||||
|
||||
documents.Add(new
|
||||
{
|
||||
FileName = doc.DocumentName,
|
||||
FileType = Path.GetExtension(doc.DocumentName),
|
||||
doc.DocumentUrl,
|
||||
doc.DocumentType.DocumentType,
|
||||
Data = Convert.ToBase64String(fileBytes)
|
||||
});
|
||||
}
|
||||
|
||||
return documents;
|
||||
}
|
||||
|
||||
public async Task<object> GetDocumentById(object payload, HttpContext httpContext)
|
||||
{
|
||||
var data = DeserializePayload.Deserialize(payload);
|
||||
var documentId = DataExtractor.GetRequiredInt(data, "documentId");
|
||||
var document = await _docRepository.GetDocumentById(documentId);
|
||||
|
||||
if (document != null && !string.IsNullOrEmpty(document.DocumentUrl))
|
||||
{
|
||||
string uploadsRoot = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), ".."));
|
||||
Console.WriteLine("Uploads Root: " + uploadsRoot);
|
||||
|
||||
string relativePath = document.DocumentUrl.Replace("/", Path.DirectorySeparatorChar.ToString());
|
||||
Console.WriteLine("Relative Path: " + relativePath);
|
||||
|
||||
string filePath = uploadsRoot + relativePath;
|
||||
Console.WriteLine("File Path: " + filePath);
|
||||
|
||||
if (!File.Exists(filePath))
|
||||
throw new FileNotFoundException("Document file not found.");
|
||||
|
||||
byte[] fileBytes = await File.ReadAllBytesAsync(filePath);
|
||||
|
||||
return new
|
||||
{
|
||||
FileName = document.DocumentName,
|
||||
FileType = Path.GetExtension(document.DocumentName),
|
||||
document.DocumentUrl,
|
||||
document.DocumentType.DocumentType,
|
||||
Data = Convert.ToBase64String(fileBytes)
|
||||
};
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Document not found or invalid document data.");
|
||||
}
|
||||
|
||||
public async Task<object> RemoveDocument(object payload, HttpContext httpContext)
|
||||
{
|
||||
await _uow.BeginAsync();
|
||||
try
|
||||
{
|
||||
var data = DeserializePayload.Deserialize(payload);
|
||||
var documentId = DataExtractor.GetRequiredInt(data, "documentId");
|
||||
var result = await _docRepository.RemoveDocument(documentId);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
throw new NotFoundException("Document not found");
|
||||
}
|
||||
|
||||
await _uow.CommitAsync();
|
||||
|
||||
return new { success = true, message = "Document removed successfully" };
|
||||
}
|
||||
catch
|
||||
{
|
||||
await _uow.RollbackAsync();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<DocumentDownloadModel> GetFileBytesById(int documentId)
|
||||
{
|
||||
var document = await _docRepository.GetDocumentById(documentId);
|
||||
|
||||
if (document == null || string.IsNullOrEmpty(document.DocumentUrl))
|
||||
throw new NotFoundException("Document record not found.");
|
||||
|
||||
string uploadsRoot = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), ".."));
|
||||
string relativePath = document.DocumentUrl.Replace("/", Path.DirectorySeparatorChar.ToString());
|
||||
string filePath = uploadsRoot + relativePath;
|
||||
|
||||
if (!File.Exists(filePath))
|
||||
throw new FileNotFoundException("Physical file is missing on the server.");
|
||||
|
||||
byte[] fileBytes = await File.ReadAllBytesAsync(filePath);
|
||||
|
||||
return new DocumentDownloadModel
|
||||
{
|
||||
FileName = document.DocumentName,
|
||||
FileType = Path.GetExtension(document.DocumentName),
|
||||
FileData = fileBytes
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user