Run code after HttpHandler has finished executing

407 views Asked by At

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();
}
2

There are 2 answers

2
wazz On

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.
}
1
Brett Caswell On

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)