Implemented functionality to whitelist file extensions during upload to S3

This commit is contained in:
ashutosh.nehete 2025-04-26 16:01:35 +05:30
parent eee07fa409
commit fc050631e7
13 changed files with 260 additions and 204 deletions

View File

@ -2,7 +2,6 @@
{
public class AddCommentDto
{
public Guid Id { get; set; } = Guid.Empty;
public Guid TicketId { get; set; } = Guid.Empty;
public Guid AuthorId { get; set; }
public string MessageText { get; set; } = string.Empty;

View File

@ -2,7 +2,6 @@
{
public class CreateTicketDto
{
public Guid Id { get; set; } = Guid.Empty;
public string Subject { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public Guid StatusId { get; set; }

View File

@ -2,7 +2,6 @@
{
public class ForumAttachmentDto
{
public Guid Id { get; set; } = Guid.Empty;
public Guid TicketId { get; set; } = Guid.Empty;
public Guid? CommentId { get; set; }
public string FileName { get; set; } = string.Empty;

View File

@ -0,0 +1,14 @@
namespace Marco.Pms.Model.Dtos.Forum
{
public class UpdateAttachmentDto
{
public Guid Id { get; set; }
public Guid TicketId { get; set; } = Guid.Empty;
public Guid? CommentId { get; set; }
public string FileName { get; set; } = string.Empty;
public string? Base64Data { get; set; }
public int FileSize { get; set; }
public string ContentType { get; set; } = string.Empty;
public DateTime SentAt { get; set; }
}
}

View File

@ -8,6 +8,6 @@
public string MessageText { get; set; } = string.Empty;
public DateTime SentAt { get; set; }
public Guid? ParentMessageId { get; set; } // For threaded replies
public ICollection<ForumAttachmentDto>? Attachments { get; set; }
public ICollection<UpdateAttachmentDto>? Attachments { get; set; }
}
}

View File

@ -11,7 +11,7 @@
public DateTime CreatedAt { get; set; }
public int LinkedProjectId { get; set; }
public int? LinkedActivityId { get; set; } // task or project ID
public ICollection<ForumAttachmentDto>? Attachments { get; set; }
public ICollection<UpdateAttachmentDto>? Attachments { get; set; }
public Guid PriorityId { get; set; }
public ICollection<Guid>? TagIds { get; set; }
public int TenantId { get; set; }

View File

@ -77,6 +77,16 @@ namespace Marco.Pms.Model.Mapper
FileId = fileId,
};
}
public static TicketAttachment ToTicketAttachmentFromUpdateAttachmentDto(this UpdateAttachmentDto AttachmentDto, Guid ticketId, Guid fileId, Guid? commentId = null)
{
return new TicketAttachment
{
TicketId = ticketId,
CommentId = commentId,
FileName = AttachmentDto.FileName,
FileId = fileId,
};
}
public static Document ToDocumentFromForumAttachmentDto(this ForumAttachmentDto AttachmentDto, string objectKey, string thumbS3Key, DateTime uploadedAt, int tenantId)
{
@ -92,6 +102,20 @@ namespace Marco.Pms.Model.Mapper
TenantId = tenantId
};
}
public static Document ToDocumentFromUpdateAttachmentDto(this UpdateAttachmentDto AttachmentDto, string objectKey, string thumbS3Key, DateTime uploadedAt, int tenantId)
{
return new Document
{
FileName = AttachmentDto.FileName,
ContentType = AttachmentDto.ContentType,
S3Key = objectKey,
ThumbS3Key = thumbS3Key,
Base64Data = AttachmentDto.Base64Data,
FileSize = AttachmentDto.FileSize,
UploadedAt = uploadedAt,
TenantId = tenantId
};
}
public static ForumTicketVM ToForumTicketVMFromTicketForum(this TicketForum ticket, Employee employee)
{
return new ForumTicketVM

View File

@ -57,7 +57,7 @@ namespace MarcoBMS.Services.Controllers
foreach (var attendanceLog in lstAttendance)
{
string objectKey = attendanceLog.Document.S3Key;
string preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(objectKey);
string preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(objectKey);
attendanceLogVMs.Add(attendanceLog.ToAttendanceLogVMFromAttendanceLog(preSignedUrl, preSignedUrl));
}
return Ok(ApiResponse<object>.SuccessResponse(attendanceLogVMs, System.String.Format("{0} Attendance records fetched successfully", lstAttendance.Count), 200));
@ -509,33 +509,16 @@ namespace MarcoBMS.Services.Controllers
if (Image != null && Image.ContentType != null)
{
byte[] fileBytes;
if (string.IsNullOrEmpty(Image.Base64Data))
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
try
{
//If base64 has a data URI prefix, strip it
var base64 = Image.Base64Data.Contains(",")
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
: Image.Base64Data;
fileBytes = Convert.FromBase64String(base64);
}
catch (Exception ex)
{
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); ;
}
using var stream = new MemoryStream(fileBytes);
string fileName = _s3Service.GenerateFileName(Image.ContentType, TenantId, "Attendance");
objectKey = await _s3Service.UploadFileAsync(stream, fileName, Image.ContentType);
preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(objectKey);
objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, TenantId, "Attendance");
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(objectKey);
document = new Document
{
FileName = Image.FileName ?? fileName,
FileName = Image.FileName ?? "",
ContentType = Image.ContentType,
S3Key = objectKey,
Base64Data = Image.Base64Data,

View File

@ -62,34 +62,14 @@ namespace Marco.Pms.Services.Controllers
{
foreach (var attachmentDto in createTicketDto.Attachments)
{
byte[] fileBytes;
var Image = attachmentDto;
if (string.IsNullOrEmpty(Image.Base64Data))
{
_logger.LogError("Base64 data is missing");
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
}
try
{
//If base64 has a data URI prefix, strip it
var base64 = Image.Base64Data.Contains(",")
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
: Image.Base64Data;
fileBytes = Convert.FromBase64String(base64);
}
catch (Exception ex)
{
_logger.LogError("{error}", ex.Message);
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); ;
}
using var stream = new MemoryStream(fileBytes);
string fileName = _s3Service.GenerateFileName(Image.ContentType, tenantId, string.Empty);
var objectKey = await _s3Service.UploadFileAsync(stream, fileName, Image.ContentType);
var objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, tenantId, "Forum");
Document document = attachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, createTicketDto.CreatedAt, tenantId);
_context.Documents.Add(document);
@ -139,7 +119,7 @@ namespace Marco.Pms.Services.Controllers
string preSignedUrl = string.Empty;
if (document != null)
{
preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
}
attachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
}
@ -198,40 +178,20 @@ namespace Marco.Pms.Services.Controllers
{
if (!existingattachmentids.Contains(attachmentDto.Id) && attachmentDto.TicketId != updateTicketDto.Id)
{
byte[] fileBytes;
var Image = attachmentDto;
if (string.IsNullOrEmpty(Image.Base64Data))
{
_logger.LogError("Base64 data is missing");
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
}
try
{
//If base64 has a data URI prefix, strip it
var base64 = Image.Base64Data.Contains(",")
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
: Image.Base64Data;
fileBytes = Convert.FromBase64String(base64);
}
catch (Exception ex)
{
_logger.LogError("{error}", ex.Message);
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); ;
}
var objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, tenantId, "Forum");
using var stream = new MemoryStream(fileBytes);
string fileName = _s3Service.GenerateFileName(Image.ContentType, tenantId, string.Empty);
var objectKey = await _s3Service.UploadFileAsync(stream, fileName, Image.ContentType);
Document document = attachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, updateTicketDto.CreatedAt, tenantId);
Document document = attachmentDto.ToDocumentFromUpdateAttachmentDto(objectKey, objectKey, updateTicketDto.CreatedAt, tenantId);
_context.Documents.Add(document);
await _context.SaveChangesAsync();
var attachment = attachmentDto.ToTicketAttachmentFromForumAttachmentDto(ticketForum.Id, document.Id);
var attachment = attachmentDto.ToTicketAttachmentFromUpdateAttachmentDto(ticketForum.Id, document.Id);
attachments.Add(attachment);
}
}
@ -313,7 +273,7 @@ namespace Marco.Pms.Services.Controllers
string preSignedUrl = string.Empty;
if (document != null)
{
preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
}
if (attachment.CommentId == null)
{
@ -376,33 +336,14 @@ namespace Marco.Pms.Services.Controllers
{
foreach (var attachmentDto in addCommentDto.Attachments)
{
byte[] fileBytes;
var Image = attachmentDto;
if (string.IsNullOrEmpty(Image.Base64Data))
{
_logger.LogError("Base64 data is missing");
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
}
try
{
//If base64 has a data URI prefix, strip it
var base64 = Image.Base64Data.Contains(",")
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
: Image.Base64Data;
fileBytes = Convert.FromBase64String(base64);
}
catch (Exception ex)
{
_logger.LogError("{error}", ex.Message);
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); ;
}
using var stream = new MemoryStream(fileBytes);
string fileName = _s3Service.GenerateFileName(Image.ContentType, tenantId, string.Empty);
var objectKey = await _s3Service.UploadFileAsync(stream, fileName, Image.ContentType);
var objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, tenantId, "Forum");
Document document = attachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, addCommentDto.SentAt, tenantId);
_context.Documents.Add(document);
@ -428,7 +369,7 @@ namespace Marco.Pms.Services.Controllers
string preSignedUrl = string.Empty;
if (document != null)
{
preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
}
attachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
}
@ -461,46 +402,31 @@ namespace Marco.Pms.Services.Controllers
List<TicketAttachment> existingAttachments = await _context.TicketAttachments.Where(a => a.CommentId == updateComment.Id).ToListAsync();
var existingattachmentids = existingAttachments.Select(a => a.Id).ToList();
var attachmentDtoids = updateCommentDto.Attachments.Select(a => a.Id).ToList();
foreach (var attachmentDto in updateCommentDto.Attachments)
List<Guid> attachmentDtoids = new List<Guid>();
if (updateCommentDto.Attachments != null)
{
if (!existingattachmentids.Contains(attachmentDto.Id) && attachmentDto.CommentId != updateComment.Id)
attachmentDtoids = updateCommentDto.Attachments.Select(a => a.Id).ToList();
foreach (var attachmentDto in updateCommentDto.Attachments)
{
byte[] fileBytes;
var Image = attachmentDto;
if (string.IsNullOrEmpty(Image.Base64Data))
if (!existingattachmentids.Contains(attachmentDto.Id) && attachmentDto.CommentId != updateComment.Id)
{
_logger.LogError("Base64 data is missing");
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
var Image = attachmentDto;
if (string.IsNullOrEmpty(Image.Base64Data))
{
_logger.LogError("Base64 data is missing");
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
}
var objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, tenantId, "Forum");
Document document = attachmentDto.ToDocumentFromUpdateAttachmentDto(objectKey, objectKey, existingComment.SentAt, tenantId);
_context.Documents.Add(document);
await _context.SaveChangesAsync();
var attachment = attachmentDto.ToTicketAttachmentFromUpdateAttachmentDto(existingComment.TicketId, document.Id, updateComment.Id);
attachments.Add(attachment);
}
try
{
//If base64 has a data URI prefix, strip it
var base64 = Image.Base64Data.Contains(",")
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
: Image.Base64Data;
fileBytes = Convert.FromBase64String(base64);
}
catch (Exception ex)
{
_logger.LogError("{error}", ex.Message);
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); ;
}
using var stream = new MemoryStream(fileBytes);
string fileName = _s3Service.GenerateFileName(Image.ContentType, tenantId, string.Empty);
var objectKey = await _s3Service.UploadFileAsync(stream, fileName, Image.ContentType);
Document document = attachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, existingComment.SentAt, tenantId);
_context.Documents.Add(document);
await _context.SaveChangesAsync();
var attachment = attachmentDto.ToTicketAttachmentFromForumAttachmentDto(existingComment.TicketId, document.Id, updateComment.Id);
attachments.Add(attachment);
}
}
if (attachments.Count != 0)
@ -537,7 +463,7 @@ namespace Marco.Pms.Services.Controllers
string preSignedUrl = string.Empty;
if (document != null)
{
preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
}
attachmentVMs.Add(attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl));
}
@ -568,32 +494,13 @@ namespace Marco.Pms.Services.Controllers
foreach (var forumAttachmentDto in forumAttachmentDtos)
{
byte[] fileBytes;
if (string.IsNullOrEmpty(forumAttachmentDto.Base64Data))
{
_logger.LogError("Base64 data is missing");
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
}
try
{
//If base64 has a data URI prefix, strip it
var base64 = forumAttachmentDto.Base64Data.Contains(",")
? forumAttachmentDto.Base64Data.Substring(forumAttachmentDto.Base64Data.IndexOf(",") + 1)
: forumAttachmentDto.Base64Data;
fileBytes = Convert.FromBase64String(base64);
}
catch (Exception ex)
{
_logger.LogError("{error}", ex.Message);
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); ;
}
using var stream = new MemoryStream(fileBytes);
string fileName = _s3Service.GenerateFileName(forumAttachmentDto.ContentType, tenantId, string.Empty);
var objectKey = await _s3Service.UploadFileAsync(stream, fileName, forumAttachmentDto.ContentType);
var objectKey = await _s3Service.UploadFileAsync(forumAttachmentDto.Base64Data, tenantId, "Forum");
Document document = forumAttachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, forumAttachmentDto.SentAt, tenantId);
_context.Documents.Add(document);
@ -603,7 +510,7 @@ namespace Marco.Pms.Services.Controllers
_context.TicketAttachments.Add(attachment);
await _context.SaveChangesAsync();
string preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
string preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
TicketAttachmentVM attachmentVM = attachment.ToTicketAttachmentVMFromTicketAttachment(preSignedUrl, preSignedUrl);
ticketAttachmentVMs.Add(attachmentVM);
@ -668,7 +575,7 @@ namespace Marco.Pms.Services.Controllers
string preSignedUrl = string.Empty;
if (document != null)
{
preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
}
if (attachment.CommentId == null)
{
@ -743,7 +650,7 @@ namespace Marco.Pms.Services.Controllers
string preSignedUrl = string.Empty;
if (document != null)
{
preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
}
if (attachment.CommentId == null)
{
@ -842,7 +749,7 @@ namespace Marco.Pms.Services.Controllers
string preSignedUrl = string.Empty;
if (document != null)
{
preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(document.S3Key);
}
if (attachment.CommentId == null)
{

View File

@ -38,28 +38,9 @@ namespace MarcoBMS.Services.Controllers
{
if (string.IsNullOrEmpty(Image.Base64Data))
return BadRequest("Base64 data is missing");
byte[] fileBytes;
try
{
//If base64 has a data URI prefix, strip it
var base64 = Image.Base64Data.Contains(",")
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
: Image.Base64Data;
fileBytes = Convert.FromBase64String(base64);
}
catch (Exception error)
{
//return BadRequest("Invalid base64 string.");
return BadRequest(error);
}
using var stream = new MemoryStream(fileBytes);
var objectKey = await _s3Service.UploadFileAsync(stream, Image.FileName, Image.ContentType);
var objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, 1, "Forum");
//var objectKey = await _s3Service.UploadFileAsync(Image.FileName, Image.ContentType);
var preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(objectKey);
var preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(objectKey);
return Ok(new
{

View File

@ -28,6 +28,8 @@
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="9.0.0" />
<PackageReference Include="Mime-Detective" Version="24.12.2" />
<PackageReference Include="Mime-Detective.Definitions.Exhaustive" Version="24.12.2" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="2.1.0" />

View File

@ -4,6 +4,7 @@ using Amazon.S3.Transfer;
using Marco.Pms.Model.Utilities;
using MarcoBMS.Services.Service;
using Microsoft.Extensions.Options;
using MimeDetective;
namespace Marco.Pms.Services.Service
{
@ -13,10 +14,12 @@ namespace Marco.Pms.Services.Service
private readonly IAmazonS3 _s3Client;
private readonly string _bucketName = "your-bucket-name";
private readonly ILoggingService _logger;
private readonly IConfiguration _configuration;
public S3UploadService(IOptions<AWSSettings> awsOptions, ILoggingService logger)
public S3UploadService(IOptions<AWSSettings> awsOptions, ILoggingService logger, IConfiguration configuration)
{
_logger = logger;
_configuration = configuration;
var settings = awsOptions.Value;
var region = Amazon.RegionEndpoint.GetBySystemName(settings.Region);
@ -25,35 +28,57 @@ namespace Marco.Pms.Services.Service
_s3Client = new AmazonS3Client(settings.AccessKey, settings.SecretKey, region);
}
//public async Task<string> UploadFileAsync(string fileName, string contentType)
public async Task<string> UploadFileAsync(Stream fileStream, string fileName, string contentType)
public async Task<string> UploadFileAsync(string base64Data, int tenantId, string tag)
{
// Generate a unique object key (you can customize this)
var objectKey = $"{fileName}";
byte[] fileBytes;
var uploadRequest = new TransferUtilityUploadRequest
//If base64 has a data URI prefix, strip it
var base64 = base64Data.Contains(",")
? base64Data.Substring(base64Data.IndexOf(",") + 1)
: base64Data;
var allowedFilesType = _configuration.GetSection("WhiteList:ContentType")
.GetChildren()
.Select(x => x.Value)
.ToList();
string fileType = GetContentTypeFromBase64(base64);
if (allowedFilesType != null && allowedFilesType.Contains(fileType))
{
InputStream = fileStream,
Key = objectKey,
BucketName = _bucketName,
ContentType = contentType,
AutoCloseStream = true
};
try
{
var transferUtility = new TransferUtility(_s3Client);
await transferUtility.UploadAsync(uploadRequest);
_logger.LogInfo("File uploaded to Amazon S3");
return objectKey;
}
catch (Exception ex)
{
_logger.LogError("{error} while uploading file to S3", ex.Message);
return string.Empty;
string fileName = GenerateFileName(fileType, tenantId, tag);
fileBytes = Convert.FromBase64String(base64);
using var fileStream = new MemoryStream(fileBytes);
// Generate a unique object key (you can customize this)
var objectKey = $"{fileName}";
var uploadRequest = new TransferUtilityUploadRequest
{
InputStream = fileStream,
Key = objectKey,
BucketName = _bucketName,
ContentType = fileType,
AutoCloseStream = true
};
try
{
var transferUtility = new TransferUtility(_s3Client);
await transferUtility.UploadAsync(uploadRequest);
_logger.LogInfo("File uploaded to Amazon S3");
return objectKey;
}
catch (Exception ex)
{
_logger.LogError("{error} while uploading file to S3", ex.Message);
return string.Empty;
}
}
throw new InvalidOperationException("Unsupported file type.");
}
public async Task<string> GeneratePreSignedUrlAsync(string objectKey)
public string GeneratePreSignedUrlAsync(string objectKey)
{
int expiresInMinutes = 1;
int expiresInMinutes = 10;
var request = new GetPreSignedUrlRequest
{
BucketName = _bucketName,
@ -95,11 +120,116 @@ namespace Marco.Pms.Services.Service
}
public string GenerateFileName(string contentType, int tenantId, string? name)
{
string extenstion = contentType.Split("/")[1];
if (string.IsNullOrEmpty(name))
return $"{tenantId}_{DateTime.UtcNow:yyyyMMddHHmmssfff}.{extenstion}";
return $"{name}_{tenantId}_{DateTime.UtcNow:yyyyMMddHHmmssfff}.{extenstion}";
string extenstion = GetExtensionFromMimeType(contentType);
if (string.IsNullOrEmpty(name))
return $"{tenantId}_{DateTime.UtcNow:yyyyMMddHHmmssfff}{extenstion}";
return $"{name}_{tenantId}_{DateTime.UtcNow:yyyyMMddHHmmssfff}{extenstion}";
}
public string GetExtensionFromMimeType(string contentType)
{
switch (contentType.ToLowerInvariant())
{
case "application/pdf":
return ".pdf";
case "application/msword":
return ".doc";
case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
return ".docx";
case "application/vnd.ms-excel":
return ".xls";
case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
return ".xlsx";
case "application/mspowerpoint":
return ".ppt";
case "application/vnd.openxmlformats-officedocument.presentationml.presentation":
return ".pptx";
case "text/plain":
return ".txt";
case "application/rtf":
return ".rtf";
case "image/jpeg":
return ".jpg";
case "image/png":
return ".png";
case "image/gif":
return ".gif";
case "image/bmp":
return ".bmp";
case "text/csv":
return ".csv";
default:
return ""; // or ".bin", or throw an error, based on your needs
}
}
public string GetContentTypeFromBase64(string base64String)
{
if (string.IsNullOrEmpty(base64String))
{
return string.Empty; // Or handle the empty case as needed
}
try
{
// 1. Decode the Base64 string to a byte array
byte[] decodedBytes = Convert.FromBase64String(base64String);
// 2. Create a ContentInspector (using default definitions for this example)
var inspector = new ContentInspectorBuilder()
{
Definitions = MimeDetective.Definitions.DefaultDefinitions.All()
}.Build();
// 3. Inspect the byte array to determine the content type
var results = inspector.Inspect(decodedBytes);
if (results.Any())
{
var bestMatch = results
.OrderByDescending(r => r.Points)
.FirstOrDefault();
if (bestMatch?.Definition?.File?.MimeType != null)
{
return bestMatch.Definition.File.MimeType;
}
else
{
_logger.LogError("Warning: Could not find MimeType, Type, or ContentType property in Definition.");
return "application/octet-stream";
}
}
else
{
return "application/octet-stream"; // Default if type cannot be determined
}
}
catch (FormatException)
{
// Handle cases where the input string is not valid Base64
Console.WriteLine("Error: Invalid Base64 string.");
return null;
}
catch (Exception ex)
{
// Handle other potential errors during decoding or inspection
Console.WriteLine($"An error occurred: {ex.Message}");
return null;
}
}
}
}

View File

@ -86,6 +86,24 @@
"SecretKey": "NTS5XXgZINQbU6ctpNuLXtIY/Qk9GCgD9Rr5yNJP",
"Region": "us-east-1",
"BucketName": "testenv-marco-pms-documents"
},
"WhiteList": {
"ContentType": [
"application/pdf", // pdf
"application/msword", // Doc
"application/vnd.openxmlformats-officedocument.wordprocessingml.document", //docx
"application/vnd.ms-excel", //xls
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", //xlsx
"application/mspowerpoint", //ppt
"application/vnd.openxmlformats-officedocument.presentationml.presentation", //pptx
"text/plain", //txt
"application/rtf", //rtf
"text/csv", //csv
"image/jpg", //jpg
"image/jpeg", //jpeg
"image/png", //png
"image/gif", //gif
"image/bmp" //bmp
]
}
}