1

I have the following code in my Controller class:

[HttpPost]
public async Task<IActionResult> GetDataFile(string id, [FromBody] DataLog log)
{
   FileStream fileStream = System.IO.File.OpenRead($"{dataFile}_{id}.log");
   //using a using block or Close prevents the download...
   return File(fileStream, "application/octet-stream");
}

The file should exist temporarily, so when the client finished with the download, the server should delete the file.

I know that while the stream is open, I can't close it.

What callback should I use? Is there a best practice for this?

Nestor
  • 8,194
  • 7
  • 77
  • 156
  • i would add a resource for http delete so its up to the client to notify that it has succeeded and should delete the file. – Daniel A. White Mar 25 '19 at 18:51
  • There is no way to know on the server side whether the client successfully downloaded and processed the file without some kind of callback mechanism. Even if the file was fully downloaded, the client may break (pull out the plug for example) before processing the last part. – Jesse de Wit Mar 25 '19 at 21:12

1 Answers1

3

You can do something like this:

public FileResult GetDataFile(string id, [FromBody] DataLog log)
{
    var bytes = System.IO.File.ReadAllBytes("<absolute path of file here>");
    System.IO.File.Delete("<absolute path of file here>");
    return File(bytes, "application/octet-stream", "<name of file>");
}

So, you are reading the file into the byte array, then deleting the physical file and returning the byte array to the client.

Nestor
  • 8,194
  • 7
  • 77
  • 156
prinkpan
  • 2,117
  • 1
  • 19
  • 32
  • Thanks, it solves the problem of deletion :) However, the question still stands of how to detect if the client is done with the downloading (for example if the completion time should be save to a database). I leave the question open for the time being to see if anyone comes up with a more universal approach :) – Nestor Mar 25 '19 at 20:58
  • The client is done downloading the file when the response is complete. Until that time, the server is still streaming the response because the file is the response. – Chris Pratt Mar 26 '19 at 13:38
  • @ChrisPratt Yes, but the server should detect if the response is served… To give an example: when your son is poking you, you are aware of that when he stops even though he stops the poking and not you :) I'd definitely add an event as `ResponseSent` with parameters. – Nestor Mar 26 '19 at 14:25
  • @Nestor, there are several other scenarios which come into the picture. Like, if the user cancels the file download, if the network cuts-off after it was partially downloaded or the network went down after last bit was sent from the server but before it can receive a callback. If we have as you said a `ResponseSent` event, we also need `ResponseError` event which will be too broad. There are browsers which can pause and continue downloads, how should we handle those? – prinkpan Mar 26 '19 at 14:47
  • Those browsers send some command back to the server - and those commands could trigger events (like `ResponsePaused` and `ResponseResumed`). I learned that we can have progress feedback with the http client so it could be well known how much of the response is downloaded. I guess this could be done, but I accept the fact that there are a large number of circumstances that could affect the events. – Nestor Mar 26 '19 at 15:25