Web Api - 如何检测响应何时完成发送

时间:2013-11-22 04:55:10

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

在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,但似乎没有太多有用的回应。

2 个答案:

答案 0 :(得分:11)

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

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

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。这样您就不需要先生成文件,然后担心以后删除它。

答案 1 :(得分:0)

我们在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;