0

I want to delete file just after this is downloaded.

I am using .Net Core MVC 6 C# Controlller.

public IActionResult DownloadPDFReport(string fileName)
        {
            string appBaseUrl = _webHostEnvironment.WebRootPath;

            // concatenating  FileName + FileExtension
            var fileNameToSave = String.Concat(fileName, ".pdf");

            // Combines two strings into a path.
            var filepath = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "pdf_files")).Root + $@"\{fileNameToSave}";

            var verification = _context.Cases.Where(x => x.Id == fileName).FirstOrDefault();
            if (verification == null)
            {
                return NotFound();
            }

            var doc = _context.EAddress_Documents.Where(x => x.CaseID == fileName).FirstOrDefault();

            var reportModel = new ReportViewModel
            {
                CaseID = fileName,
                ReferenceId = verification.Id,
                ApplicantName = "Gopal Sharma",
                Address = verification.Address,
                ClientName = "EXL Services",
                PhoneNumber = "9876543210",
                Latitude = verification.Latitude,
                Longitude = verification.Longitude,
                
                NearbyLocationImageURL = doc.NearbyLocationImage_FilePath
            };

            PdfService.GenerateReport(filepath, reportModel);

            string newFileName = verification.ApplicantName + "_" + DateTime.Now + ".pdf";
            string filePath = "~/pdf_files/" + fileName + ".pdf";
            Response.Headers.Add("Content-Disposition", "inline; filename=" + newFileName + "");
            return File(filePath, "application/pdf");
        }

Any help on this ?

I also tried to make an attribue like below. But this is Old MVC Code. This code does not work in .NET Core MVC 6 C#.

public class DeleteFileAttribute : ActionFilterAttribute
    {
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            filterContext.HttpContext.Response.Flush();
            var filePathResult = filterContext.Result as FilePathResult;
            if (filePathResult != null)
            {
                System.IO.File.Delete(filePathResult.FileName);
            }
        }
    }

enter image description here

Second One--

enter image description here

GOPAL SHARMA
  • 657
  • 2
  • 12
  • 37
  • 1. Please show to code where you and how you save this file 2. I am not sure that doing this via attribute it is a good idea. – Mykyta Halchenko Apr 19 '22 at 09:06
  • @Skalpel02 - I am saving in wwwroot folder var filepath = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "pdf_files")).Root + $@"\{fileNameToSave}"; – GOPAL SHARMA Apr 19 '22 at 09:07
  • This task should not be done via attribute, it is awful solution for this. What I can propose you is to create an additional method of endpoint which is going to be called after this controller's method you execute, let's name it "RemoveFile(string path)". Once you download the file file - call the method and remove file as per path you passed. – Mykyta Halchenko Apr 19 '22 at 09:10
  • @Skalpel02 - Can you suggest some example or link ? – GOPAL SHARMA Apr 19 '22 at 09:12
  • No need to use attribute, just build the filePath on client side and path to the second method you will create, see suggested answer. – Mykyta Halchenko Apr 19 '22 at 09:23
  • Downloaded by whom? Is your server downloading a file from another server, or is your client downloading a file from your server? – Caius Jard Apr 19 '22 at 10:26
  • @CaiusJard - Client or you can say user will download the file on a button click. – GOPAL SHARMA Apr 19 '22 at 12:01
  • 1
    So you want to delete a file from your server aftersending it to a normal user in the world who downloads it using his browser. Do you generate the file? I'm wondering if you just generate it in memory, the problem is solved automatically – Caius Jard Apr 19 '22 at 13:55

2 Answers2

0

What I can propose to do is:

  1. You stay the functionality you have as it is and call the method DownloadPDFReport.

  2. After that create an method RemovePDFReport in the same controller with string filePath parameter, something like that:

    public IActionResult RemovePDFReport(string filePath) {
    
       System.IO.File.Delete(filePath);
    
       return Ok();
    
    }
    

3.From client side just call the RemovePDFReport method after DownloadPDFReport and path the built path(you know how to build it on client-side via new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "pdf_files")).Root + $@"\{fileNameToSave}";)

Mykyta Halchenko
  • 720
  • 1
  • 3
  • 21
  • I want file deletion in single call only. No separate call to delete the file. – GOPAL SHARMA Apr 19 '22 at 09:25
  • 1
    @GOPALSHARMA in this scenario I can propose you to use cache - generate the guid(session token) and store in memory in dictionary , where Guid - file session id and string is filePath, and create a worker/cache expiration date that will remove it. It is good way to delete, if you want to do it in ugly way - do it via attribute, – Mykyta Halchenko Apr 19 '22 at 09:28
  • Okay Thanks, I will try this way – GOPAL SHARMA Apr 19 '22 at 09:29
0

After struggling 1 day, I found this solution. Before, I was writing/generating a file at a particular location, then trying to delete that. That way, If I clicked again to download file, It used to throw exception that file is in already in used by some other process.

So now, I found a way in which I don't need to write the file.. Just write your data in stream, then download directly.

Below Is The Simple and Clear Code-

[HttpGet]
        public IActionResult DownloadPDF()
        {
            using (MemoryStream memoryStream = new())
            {
                Document pdfDoc = new Document(PageSize.A4, 10f, 10f, 100f, 0f);

                iTextSharp.text.pdf.PdfWriter writer = iTextSharp.text.pdf.PdfWriter.GetInstance(pdfDoc, memoryStream);

                pdfDoc.Open();

                PdfPTable headerContentTable = new PdfPTable(1)
                {
                    WidthPercentage = 100f,
                    HorizontalAlignment = Element.ALIGN_CENTER,
                    SpacingBefore = 10f,
                    SpacingAfter = 10f
                };

                headerContentTable.AddCell(new PdfPCell(new Phrase(new Chunk("Employee Address eVerification Report", FontFactory.GetFont(Font.COURIER.ToString(), 16, Font.BOLD, BaseColor.Black)))) { HorizontalAlignment = Element.ALIGN_CENTER, Border = 0, BackgroundColor = BaseColor.Blue, PaddingBottom = 10, PaddingTop = 8 });
                pdfDoc.Add(headerContentTable);

                pdfDoc.Close();
                
                return File(memoryStream.ToArray(), "application/pdf", "Gopal_" + DateTime.Now + ".pdf");
            }
        }
GOPAL SHARMA
  • 657
  • 2
  • 12
  • 37