Matt Burland
Matt Burland

Reputation: 45155

Returning a filestream - how to know when it's done

I have a controller which has a function that will return a file. The file is generated on the server as a temp file and then streamed via a HttpResponseMessage. What I'd like to do, is delete the file after I've finished sending it (maybe in the future we might keep them for a little while in case the exact same request is made again). I have something like this:

    [HttpGet]
    public HttpResponseMessage GetReport()
    {
        string fileName = //function that creates the file and returns the filename...
        HttpResponseMessage response = new HttpResponseMessage();
        response.Content = new StreamContent(new FileStream(fileName, FileMode.Open, FileAccess.Read));
        response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
        response.Content.Headers.ContentDisposition.FileName = "test.docx";

        //File.Delete(fileName);
        return response;
    }

I can't delete the file at the commented out point above because the file is in use at that point. So is there an event or something that will be fired once the stream has finished being sent so I can handle deleting?

I could, of course, just start a task to wait some (hopefully sufficiently long) period of time and then delete, but that seems a little hit-or-miss.

Upvotes: 0

Views: 116

Answers (2)

NathanAldenSr
NathanAldenSr

Reputation: 7961

Because you mentioned keeping the files around for awhile (potentially), you will need some kind of expiration architecture. Create a database table that tracks these temporary file system objects along with an expiration timestamp. Then, create a scheduled task using Windows Task Scheduler or a library like Quartz.NET to periodically query for expired objects and delete them.

I do this in my own projects for cleaning up files that were uploaded by the user but aren't necessarily used because the user canceled the encompassing process.

The tricky part is defining what constitutes a successful response. Is the response successful because the client received all the data and acted upon it? If so, then only the client has all the information necessary to determine if the data was received successfully. In this case, the client could perhaps tell the server that it (the client) received and acted upon the data. Then, the server could either delete the file immediately or mark it for expiration in the architecture I mentioned previously.

Upvotes: 1

Aik
Aik

Reputation: 3748

HttpResponseMessage is disposable than my suggestion is define your class derived from HttpResponseMessage and override Dispose(bool disposing) method to clean up your file.

class FileResponseMessage : HttpResponseMessage 
{
   public string FileResponseMessage(string fileName)
   {
        this.Content = new StreamContent(new FileStream(fileName, FileMode.Open, FileAccess.Read));
        this.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
        this.Content.Headers.ContentDisposition.FileName = "test.docx";
   }

   override void Dispose(bool disposing)
   {
       if(disposing)
       {
           //your cleanup
       }
   }
}

Upvotes: 1

Related Questions