【问题标题】:Run code after HttpHandler has finished executingHttpHandler 执行完毕后运行代码
【发布时间】:2018-11-27 10:11:52
【问题描述】:

HttpHandler 负责使用HttpResponse.TransmitFile 将文件下载分派给最终用户。下载完成后需要删除该文件,但如果在HttpResponse.End之前删除该文件,则该文件丢失,下载失败,HttpResponse.End之后的任何代码都不会执行。

在下载完成并且HttpResponse 结束后删除此文件的最佳方法是什么?

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

【问题讨论】:

  • 它是什么类型的文件?它有特定的内容类型吗?
  • 另外,我认为没有必要在这里调用HttpResponse.End(),事实上,我认为这个概念会抑制其他ProcessRequest 范围和可能发生的处理,包括@ 987654328@。您可能应该在这里打一个Flush() 电话。

标签: c# asp.net .net httphandler ihttphandler


【解决方案1】:

鉴于您的要求和问题,您应该使用会立即影响此处HttpResponse.OutputStream 的实现。

如果您查看HttpResponse.TransmitFile,您会注意到它不会将文件流缓冲到内存中。

将指定文件直接写入 HTTP 响应输出流,而不将其缓冲在内存中。

出于您的目的,您确实希望将其缓冲到内存中;之后,您可以删除该文件。


示例实现

实际上,这个answer to another SO question提供了一个适合处理这个问题的实现:

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

请注意,您可以直接写入HttpResponse.OutputStream,而不是使用HttpResponse 对象之外的Write 方法:

File.OpenRead(Server.MapPath(absolutePath)).CopyTo(context.Response.OutputStream)

【讨论】:

  • 关于Write 方法,我认为其中一些设置HttpResponse 对象属性的方法可能存在问题,例如Content-TypeContent-Length。对于所有这些方法,特别是CopyTo(content.Response.OutputStream),您还应该添加/指定适当和更正的Content-LengthContent-Type 标头。
【解决方案2】:

对此并不完全确定,但.End() 引发了EndRequest 事件,因此将其添加到您的http 处理程序可能会起作用。希望那会足够晚(这是筹备中的最后一个活动)。

private void Application_EndRequest(Object source, EventArgs e)
{
    // delete file here.
}

【讨论】:

  • 这个方法不会被调用
  • 我相信这是HttpModule而不是HttpHandler使用的。
猜你喜欢
  • 2015-07-19
  • 1970-01-01
  • 2021-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-20
  • 2021-08-10
  • 2012-02-08
相关资源
最近更新 更多