Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web Api - How to detect when a response has finished being sent

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

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.

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

like image 694
George Mauer Avatar asked Nov 22 '13 04:11

George Mauer


People also ask

How do you check if an API is get or post?

You can use Head also. The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response. The metainformation contained in the HTTP headers in response to a HEAD request SHOULD be identical to the information sent in response to a GET request.

How do I know if Web API is working?

API testing flow is quite simple with three main steps: Send the request with necessary input data. Get the response having output data. Verify that the response returned as expected in the requirement.


1 Answers

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.

like image 74
Kiran Avatar answered Oct 17 '22 11:10

Kiran