using Amazon.S3; using Amazon.S3.Model; using BMA.EHR.Recruit.Service.Core; using BMA.EHR.Recruit.Service.Models.Documents; using BMA.EHR.Recruit.Service.Responses.Document; using BMA.EHR.Report.Service.Data; using Microsoft.EntityFrameworkCore; using System.Drawing; using System.Net.Http.Headers; namespace BMA.EHR.Recruit.Service.Services { public class MinIOService { #region " Fields " private readonly EHRDbContext _context; private readonly IConfiguration _configuration; private readonly IWebHostEnvironment _webHostEnvironment; private readonly AmazonS3Client _s3Client; private string _bucketName = string.Empty; #endregion #region " Constructors " public MinIOService(EHRDbContext context, IConfiguration configuration, IWebHostEnvironment webHostEnvironment) { _context = context; _configuration = configuration; _webHostEnvironment = webHostEnvironment; var config = new AmazonS3Config { ServiceURL = _configuration["MinIO:Endpoint"], ForcePathStyle = true }; _s3Client = new AmazonS3Client(_configuration["MinIO:AccessKey"], _configuration["MinIO:SecretKey"], config); this._bucketName = _configuration["MinIO:BucketName"] ?? "bma-recruit"; } #endregion #region " Methods " public async Task UploadFileAsync(IFormFile file, string newFileName = "") { var fileName = ""; var fileExt = Path.GetExtension(file.FileName); if (newFileName != "") fileName = $"{newFileName}"; else fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"'); var tmpDir = Path.Combine(_webHostEnvironment.ContentRootPath, "tmp"); if (!Directory.Exists(tmpDir)) Directory.CreateDirectory(tmpDir); var tmpFile = Path.Combine(tmpDir, $"tmp_{DateTime.Now.ToString("ddMMyyyyHHmmss")}{fileExt}"); try { using (var ms = new MemoryStream()) { var id = Guid.NewGuid(); file.CopyTo(ms); var fileBytes = ms.ToArray(); System.IO.MemoryStream filestream = new System.IO.MemoryStream(fileBytes); var request = new PutObjectRequest { BucketName = _bucketName, Key = id.ToString("D"), InputStream = filestream, ContentType = file.ContentType, CannedACL = S3CannedACL.PublicRead }; await _s3Client.PutObjectAsync(request); // create document object var doc = new Document() { FileName = fileName, FileType = file.ContentType, FileSize = Convert.ToInt32(file.Length), ObjectRefId = id, CreatedDate = DateTime.Now }; await _context.Documents.AddAsync(doc); await _context.SaveChangesAsync(); return doc; } } catch { throw; } finally { File.Delete(tmpFile); } } public async Task DownloadFileAsync(Guid fileId) { try { var doc = await _context.Documents.AsQueryable() .FirstOrDefaultAsync(x => x.Id == fileId); if (doc == null) throw new Exception(GlobalMessages.FileNotFoundOnServer); using (var memoryStream = new MemoryStream()) { GetObjectRequest request = new GetObjectRequest { BucketName = _bucketName, Key = doc.ObjectRefId.ToString("D") }; using (GetObjectResponse response = await _s3Client.GetObjectAsync(request)) { using (Stream responseStream = response.ResponseStream) { responseStream.CopyTo(memoryStream); } } var fileContent = memoryStream.ToArray(); return new FileDownloadResponse { FileName = doc.FileName, FileType = doc.FileType, FileContent = fileContent }; }; } catch { throw; } } public async Task DeleteFileAsync(Guid fileId) { try { var doc = await _context.Documents.AsQueryable() .FirstOrDefaultAsync(x => x.Id == fileId); if (doc == null) throw new Exception(GlobalMessages.FileNotFoundOnServer); else { DeleteObjectRequest request = new DeleteObjectRequest { BucketName = _bucketName, Key = doc?.ObjectRefId.ToString("D") }; // delete from minio await _s3Client.DeleteObjectAsync(request); _context.Documents.Remove(doc); await _context.SaveChangesAsync(); } } catch { throw; } } public async Task GetFilePath(Guid fileId) { var doc = await _context.Documents.AsQueryable() .FirstOrDefaultAsync(x => x.Id == fileId); if (doc == null) throw new Exception(GlobalMessages.FileNotFoundOnServer); //var config = new AmazonS3Config //{ // ServiceURL = Configuration.GetValue("MinIO:Endpoint"), // ForcePathStyle = true //}; DateTime expires = DateTime.UtcNow.AddHours(6); GetPreSignedUrlRequest request = new GetPreSignedUrlRequest { BucketName = _bucketName, Key = doc?.ObjectRefId.ToString("D"), Expires = expires, }; string path = _s3Client.GetPreSignedURL(request); return path; } public Image ByteArrayToImage(byte[] bytesArr) { using (MemoryStream memstr = new MemoryStream(bytesArr)) { Image img = Image.FromStream(memstr); return img; } } #endregion } }