1

An HttpHandler is in charge of dispatching file downloads to the end user using HttpResponse.TransmitFile. This file needs to be deleted after the download is completed, however if the file is deleted before HttpResponse.End then the file is missing and the download fails, and any code after HttpResponse.End is not executed.

What would be the best way to delete this file after the download is completed and the HttpResponse is ended?

public void ProcessRequest(HttpContext context)
{
    HttpResponse r = context.Response;
    string filePath = context.Request.QueryString["filePath"];
    string fName = context.Request.QueryString["fname"];
    r.AddHeader("content-disposition", "inline; filename=\"" + fName + "\"");
    r.TransmitFile(fullPath);
    r.End();
}
Rafael
  • 1,099
  • 5
  • 23
  • 47
  • what type of file is it? does it have a specific content-type? – Brett Caswell Aug 31 '18 at 07:19
  • also, I don't think there is a need to do `HttpResponse.End()` call here, Infact, I see the notion as inhibiting to other `ProcessRequest` scopes and handling that could occur, to include `HttpModule`. You should potentially just do a `Flush()` call here. – Brett Caswell Aug 31 '18 at 07:45

2 Answers2

0

Given your requirement and issue, you should be working with implementations that immediately affect the HttpResponse.OutputStream here.

If you look up HttpResponse.TransmitFile you'll note that it does not buffer the filestream into memory.

Writes the specified file directly to an HTTP response output stream, without buffering it in memory.

For your purposes, you do want it buffered into memory; after which, you can delete the file.


Example Implementation

Actually, this answer to another SO question provides an implementation that is appropriate to handling this:

public void ProcessRequest(HttpContext context)
{
    string absolutePath = "~/your path";
    //copy to MemoryStream
    using (MemoryStream ms = new MemoryStream())
    {
        using (FileStream fs = File.OpenRead(Server.MapPath(absolutePath))) 
        { 
            fs.CopyTo(ms); 
        }
    
        //Delete file
        if(File.Exists(Server.MapPath(absolutePath)))
           File.Delete(Server.MapPath(absolutePath))
    
        //Download file
        context.Response.Clear()
        context.Response.ContentType = "image/jpg";
        context.Response.AddHeader("Content-Disposition", "attachment;filename=\"" + absolutePath + "\"");
        context.Response.BinaryWrite(ms.ToArray())
    }
    
    Response.End();
}

Note that you can write directly to the HttpResponse.OutputStream and not use Write methods off the HttpResponse object:

File.OpenRead(Server.MapPath(absolutePath)).CopyTo(context.Response.OutputStream)
Community
  • 1
  • 1
Brett Caswell
  • 1,486
  • 1
  • 13
  • 25
  • regarding the `Write` methods, I think there could be concerns with some of those methods setting properties of `HttpResponse` object, like `Content-Type` and `Content-Length`. For all of these methods, and specifically to `CopyTo(content.Response.OutputStream)`, you should add/specify appropriate and correct `Content-Length` and `Content-Type` headers as well. – Brett Caswell Aug 31 '18 at 07:50
-1

Not entirely sure about this but .End() raises the EndRequest event, so it might work to add that to your http handler. Hopefully that will be late enough (it's the final event in the pipeline).

private void Application_EndRequest(Object source, EventArgs e)
{
    // delete file here.
}
wazz
  • 4,953
  • 5
  • 20
  • 34