【问题标题】:Web Api - How to detect when a response has finished being sentWeb Api - 如何检测何时完成发送响应
【发布时间】:2015-05-29 14:53:08
【问题描述】:

在 web api 方法中,我正在生成一个文件,然后像这样将其流式传输到响应

public async Task<HttpResponseMessage> GetFile() {
    FileInfo file = generateFile();
    var msg = Request.CreateResponse(HttpStatusCode.OK);

    msg.Content = new StreamContent(file.OpenRead());
    msg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
    msg.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {FileName = file.Name};

    return msg;
}

因为这是一个生成的文件,我想在响应完成流式传输后将其删除,但我似乎无法在管道中找到一个挂钩。

我想我可以将文件的引用放在一个静态变量中,并设置一个自定义的 MessageHandler 来从同一个静态变量中提取值并删除。但是,这似乎不可能是正确的,因为使用了静态(当这应该都是每个请求时)并且因为我必须注册一个单独的路由。

我见过this question,但似乎并没有太多有用的回应。

【问题讨论】:

    标签: asp.net asp.net-web-api


    【解决方案1】:

    不错的场景!...使用消息处理程序的问题是响应写入发生在主机层和消息处理程序层以下,因此它们并不理想...

    以下是您如何做到这一点的示例:

    msg.Content = new CustomStreamContent(generatedFilePath);
    

    public class CustomStreamContent : StreamContent
    {
        string filePath;
    
        public CustomStreamContent(string filePath)
            : this(File.OpenRead(filePath))
        {
            this.filePath = filePath;
        }
    
        private CustomStreamContent(Stream fileStream)
            : base(content: fileStream)
        {
        }
    
        protected override void Dispose(bool disposing)
        {
            //close the file stream
            base.Dispose(disposing);
    
            try
            {
                File.Delete(this.filePath);
            }
            catch (Exception ex)
            {
                //log this exception somewhere so that you know something bad happened
            }
        }
    }
    

    顺便说一句,您生成此文件是因为您将一些数据转换为 PDF。如果是,那么我认为您可以为此目的使用PushStreamContent,方法是将转换后的数据直接写入响应流。这样您就不必先生成文件,然后再担心以后删除它。

    【讨论】:

    • 感谢 Kiran,我正试图用装饰器模式做这样的事情,并且因为我不能仅仅覆盖公众而把头发拉出来。在那张纸条上(而且因为你在 Web Api 上工作)我们有没有机会让 HttpContent 在未来基于接口?
    • 是的,我正在生成一个 pdf,但是通过使用 phantomjs 来完成它,所以 File 是我的基本交换格式,而不是 Stream
    【解决方案2】:

    我们在 WebAPI 中执行了相同的操作。我需要在下载表单服务器后删除文件。 我们可以创建自定义响应消息类。以文件路径为参数,传输后删除。

     public class FileResponseMessage : HttpResponseMessage
        {
            private readonly string _filePath;
    
            public FileHttpResponseMessage(string filePath)
            {
                this._filePath= filePath;
            }
    
            protected override void Dispose(bool disposing)
            {
                base.Dispose(disposing);
                Content.Dispose();
                File.Delete(_filePath);
            }
        }
    

    在下面的代码中使用这个类,一旦它被写入响应流,它将删除你的文件。

     var response = new FileResponseMessage(filePath);
     response.StatusCode = HttpStatusCode.OK;
    response.Content = new StreamContent(new FileStream(filePath, FileMode.Open, FileAccess.Read));
    response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
    {
      FileName = "MyReport.pdf"
    };
     return response;
    

    【讨论】:

    • 只应在 disposing = true 时执行 Dispose 方法中的代码。否则你会有问题。
    猜你喜欢
    • 2015-12-22
    • 1970-01-01
    • 2013-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-28
    相关资源
    最近更新 更多