20

In ASP.NET webapi, I send a temporary file to client. I open a stream to read the file and use the StreamContent on the HttpResponseMessage. Once the client receives the file, I want to delete this temporary file (without any other call from the client) Once the client recieves the file, the Dispose method of HttpResponseMessage is called & the stream is also disposed. Now, I want to delete the temporary file as well, at this point.

One way to do it is to derive a class from HttpResponseMessage class, override the Dispose method, delete this file & call the base class's dispose method. (I haven't tried it yet, so don't know if this works for sure)

I want to know if there is any better way to achieve this.

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
Bhanu Gotluru
  • 235
  • 2
  • 7
  • 1
    The above approach seems to work, but the Content needs to be disposed before the file is deleted (as the stream to the file is still open) `protected override void Dispose(bool disposing) { Content.Dispose(); FileInfo file = new FileInfo(_localFile); file.Delete(); base.Dispose(disposing); }` – Bhanu Gotluru Mar 08 '13 at 14:22

3 Answers3

16

Create your StreamContent from a FileStream having DeleteOnClose option.

return new HttpResponseMessage(HttpStatusCode.OK)
{
    Content = new StreamContent(
        new FileStream("myFile.txt", FileMode.Open, 
              FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose)
    )
};
SergeyS
  • 3,909
  • 2
  • 15
  • 17
15

Actually your comment helped solve the question... I wrote about it here:

Delete temporary file sent through a StreamContent in ASP.NET Web API HttpResponseMessage

Here's what worked for me. Note that the order of the calls inside Dispose differs from your comment:

public class FileHttpResponseMessage : HttpResponseMessage
{
    private string filePath;

    public FileHttpResponseMessage(string filePath)
    {
        this.filePath = filePath;
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);

        Content.Dispose();

        File.Delete(filePath);
    }
}
Community
  • 1
  • 1
Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
  • 2
    Just to add, the same question has been asked a month after this answer, [here](http://stackoverflow.com/questions/20137283/web-api-how-to-detect-when-a-response-has-finished-being-sent), and it's similar to this one. But instead of subclassing `HttpResponseMessage`, it do so with `StreamContent`. I feel more comfortable doing the job in that way as it is closer to the problem in question (overriding less behavior), avoiding the explicit call to `Content.Dispose();` – Chopin Mar 22 '14 at 14:52
  • Be very careful with approaches like this. The `Dispose(bool)` method is meant to be called from both `Dispose()` and from finalizers. And finalizers must NEVER throw. So you would probably want to test `disposing`, and only call `File.Delete` if `disposing` is true. – Daniel Yankowsky Oct 07 '15 at 23:15
4

I did it by reading the file into a byte[] first, deleting the file, then returning the response:

        // Read the file into a byte[] so we can delete it before responding
        byte[] bytes;
        using (var stream = new FileStream(path, FileMode.Open))
        {
            bytes = new byte[stream.Length];
            stream.Read(bytes, 0, (int)stream.Length);
        }
        File.Delete(path);

        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        result.Content = new ByteArrayContent(bytes);
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        result.Content.Headers.Add("content-disposition", "attachment; filename=foo.bar");
        return result;
UnionP
  • 1,251
  • 13
  • 26