using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using GB5Shared.Attachment;
using GB5Shared.DTO.ECM;
using GB5Shared.DTO.Framework.Login;
using GB5Shared.DTO.Framework.ResponseStandard;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using static GB5Shared.GB5Constant.Constant;
namespace FrameworkSL.Controllers.Attachment
{
///
/// Template-based attachment upload/delete.
/// Uses IAttachmentUploadService (TemplateResolutionEngine) rather than the
/// legacy Alfresco-backed IFileUploadBLL.
/// Route prefix: /Attachment/Template
///
[ApiController]
[Route("Attachment/Template")]
public class TemplateAttachmentController : ControllerBase
{
private readonly IAttachmentUploadService _uploadService;
public TemplateAttachmentController(IAttachmentUploadService uploadService)
=> _uploadService = uploadService;
// ── Upload ────────────────────────────────────────────────────
///
/// Multipart/form-data upload using the template engine for path resolution.
/// POST /Attachment/Template/Upload
/// Form fields: DocumentSetDetailId, ObjectTypeId, ObjectId, BizTransactionTypeId,
/// RowGuid, AttachmentType, Remarks, Tags, ContextDictionaryJson
///
[HttpPost("Upload")]
[DisableRequestSizeLimit]
public async Task> Upload(
IFormFile File,
[FromForm] int DocumentSetDetailId,
[FromForm] int ObjectTypeId,
[FromForm] int ObjectId,
[FromForm] int BizTransactionTypeId,
[FromForm] Guid RowGuid,
[FromForm] byte AttachmentType,
[FromForm] string? Remarks,
[FromForm] string? Tags,
[FromForm] string? ContextDictionaryJson,
[FromHeader(Name = "Login")] string LoginDTOJson,
CancellationToken ct)
{
var login = Newtonsoft.Json.JsonConvert.DeserializeObject(LoginDTOJson)!;
try
{
var contextDict = string.IsNullOrWhiteSpace(ContextDictionaryJson)
? new Dictionary()
: JsonSerializer.Deserialize>(ContextDictionaryJson)
?? new Dictionary();
var request = new AttachmentUploadRequest
{
DocumentSetDetailId = DocumentSetDetailId,
ObjectTypeId = ObjectTypeId,
ObjectId = ObjectId,
BizTransactionTypeId = BizTransactionTypeId,
RowGuid = RowGuid,
AttachmentType = AttachmentType,
Remarks = Remarks,
Tags = Tags ?? string.Empty,
ContextDictionary = contextDict
};
await using var stream = File.OpenReadStream();
var result = await _uploadService.UploadAsync(
request, stream, File.FileName, File.ContentType, login, ct)
.ConfigureAwait(false);
return await GB5Shared.ResponseStandard.Response.CreateSuccessResponse(
result, CacheKeyLevel.NOT_REQUIRED, login);
}
catch (Exception ex)
{
return await GB5Shared.ResponseStandard.Response.CreateExceptionError(
ex, CacheKeyLevel.NOT_REQUIRED, login, ex.Message, 500);
}
}
// ── Upload (Base64 / JSON body) ─────────────────────────────────
///
/// JSON-body upload — same as Upload above, but the file travels as Base64
/// inside the request body instead of multipart/form-data.
/// POST /Attachment/Template/UploadBase64
///
[HttpPost("UploadBase64")]
public async Task> UploadBase64(
[FromBody] AttachmentUploadBase64Request body,
[FromHeader(Name = "Login")] string LoginDTOJson,
CancellationToken ct)
{
var login = Newtonsoft.Json.JsonConvert.DeserializeObject(LoginDTOJson)!;
try
{
var request = new AttachmentUploadRequest
{
DocumentSetDetailId = body.DocumentSetDetailId,
ObjectTypeId = body.ObjectTypeId,
ObjectId = body.ObjectId,
BizTransactionTypeId = body.BizTransactionTypeId,
RowGuid = body.RowGuid,
AttachmentType = body.AttachmentType,
Remarks = body.Remarks,
Tags = body.Tags ?? string.Empty,
ContextDictionary = body.ContextDictionary ?? new Dictionary()
};
var fileBytes = Convert.FromBase64String(body.Base64Content);
var contentType = string.IsNullOrWhiteSpace(body.ContentType)
? "application/octet-stream"
: body.ContentType;
using var stream = new MemoryStream(fileBytes);
var result = await _uploadService.UploadAsync(
request, stream, body.FileName, contentType, login, ct)
.ConfigureAwait(false);
return await GB5Shared.ResponseStandard.Response.CreateSuccessResponse(
result, CacheKeyLevel.NOT_REQUIRED, login);
}
catch (Exception ex)
{
return await GB5Shared.ResponseStandard.Response.CreateExceptionError(
ex, CacheKeyLevel.NOT_REQUIRED, login, ex.Message, 500);
}
}
// ── Update (confirm deferred path) ──────────────────────────────
///
/// Confirms a Phase-1 deferred attachment once the caller knows the real ObjectId
/// and/or the field values its LOCATIONTEMPLATE/DOCUMENTNAMETEMPLATE tokens needed
/// (e.g. {EMP}, {Year}, {Month} in "/employee/history/{EMP}"). Re-resolves the
/// template, moves the file in storage to its final path, and updates TATTACHMENT.
/// Idempotent — retrying with the same inputs is a safe no-op.
/// POST /Attachment/Template/UpdateUploadBase64
///
[HttpPost("UpdateUploadBase64")]
public async Task> UpdateUploadBase64(
[FromBody] AttachmentResolvePathRequest body,
[FromHeader(Name = "Login")] string LoginDTOJson,
CancellationToken ct)
{
var login = Newtonsoft.Json.JsonConvert.DeserializeObject(LoginDTOJson)!;
try
{
var result = await _uploadService.ResolveDeferredPathAsync(body, login, ct)
.ConfigureAwait(false);
return await GB5Shared.ResponseStandard.Response.CreateSuccessResponse(
result, CacheKeyLevel.NOT_REQUIRED, login);
}
catch (Exception ex)
{
return await GB5Shared.ResponseStandard.Response.CreateExceptionError(
ex, CacheKeyLevel.NOT_REQUIRED, login, ex.Message, 500);
}
}
// ── Delete ────────────────────────────────────────────────────
///
/// Deletes a TATTACHMENT row and removes the physical file from storage.
/// DELETE /Attachment/Template/Delete/{attachmentId}
///
[HttpDelete("Delete/{AttachmentId:int}")]
public async Task> Delete(
int AttachmentId,
[FromHeader(Name = "Login")] string LoginDTOJson,
CancellationToken ct)
{
var login = Newtonsoft.Json.JsonConvert.DeserializeObject(LoginDTOJson)!;
try
{
await _uploadService.DeleteAsync(AttachmentId, login, ct).ConfigureAwait(false);
return await GB5Shared.ResponseStandard.Response.CreateSuccessResponse(
"Attachment deleted.", CacheKeyLevel.NOT_REQUIRED, login);
}
catch (Exception ex)
{
return await GB5Shared.ResponseStandard.Response.CreateExceptionError(
ex, CacheKeyLevel.NOT_REQUIRED, login, ex.Message, 500);
}
}
}
}