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

时间:2021-10-25 07:17:51

In a web api method I am generating a file and then streaming it to the response like so

在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;
}

because this a generated file I want to delete it after the response has finished streaming but I can't seem to find a hook in the pipeline for this.

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

I suppose that I can put a reference to the file in a static and set up a custom MessageHandler that pulls values out of this same static variable and deletes. However, this seems like it can't possibly be right both because of the use of a static (when this should all be per-request) and because I'd have to register a separate route.

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

I've seen this question but it seems to not really have much of a useful response.

我已经看到了这个问题,但似乎并没有太多有用的回应。

2 个解决方案

#1


10  

Nice scenario!...the problem with using message handlers is that response writing happens at the host layers and below message handlers layer, so they are not ideal...

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

Following is an example of how you could do it:

以下是如何执行此操作的示例:

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
        }
    }
}

By the way, are you generating this file because you are converting some data into PDF. If yes, then I think you could use PushStreamContent for this purpose by directly writing the converted data into the response stream. This way you need not generate a file first and then worry about deleting it later.

顺便说一句,您是否正在生成此文件,因为您正在将某些数据转换为PDF。如果是,那么我认为您可以通过直接将转换后的数据写入响应流来使用PushStreamContent。这样您就不需要先生成文件,然后担心以后删除它。

#2


0  

We performed same action in WebAPI. I needed to delete file just after it downloaded form server. We can create custom response message class. It takes file path as parameter and delete it once its transmitted.

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

Use this class as below code and it will delete your file once it will be written on response stream.

使用此类作为下面的代码,一旦将其写入响应流,它将删除您的文件。

 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;

#1


10  

Nice scenario!...the problem with using message handlers is that response writing happens at the host layers and below message handlers layer, so they are not ideal...

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

Following is an example of how you could do it:

以下是如何执行此操作的示例:

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
        }
    }
}

By the way, are you generating this file because you are converting some data into PDF. If yes, then I think you could use PushStreamContent for this purpose by directly writing the converted data into the response stream. This way you need not generate a file first and then worry about deleting it later.

顺便说一句,您是否正在生成此文件,因为您正在将某些数据转换为PDF。如果是,那么我认为您可以通过直接将转换后的数据写入响应流来使用PushStreamContent。这样您就不需要先生成文件,然后担心以后删除它。

#2


0  

We performed same action in WebAPI. I needed to delete file just after it downloaded form server. We can create custom response message class. It takes file path as parameter and delete it once its transmitted.

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

Use this class as below code and it will delete your file once it will be written on response stream.

使用此类作为下面的代码,一旦将其写入响应流,它将删除您的文件。

 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;