0

I am using ASP.NET FileStreamResult to send back a file as a response to the user.

It works fine on sending any file, but after calling some functions using System.Drawing to generate some files, it stuck and never send a response to the frontend. The frontend is keeping "pending for the request".

And looking at the code below, I specify once response is sent, the file will be deleted, but the file is still on the server side, that means the file is never sent out. I then stop the server, and the file is deleted on the server side, that means when I stop the server, the response is fulfilled at that time.

I already tested long request processing time and large size of file, and found they doesn't matter here. The only matter is the call to functions of System.Drawing. So I create another thread to run those functions and this problem is solved and the response can be sent out.

My question is Why calling System.Drawing and System.Windows.Forms will break ASP.NET??

I am using IIS Express as the server. also using .NET 6.

protected ActionResult SendFile(string filePath)
{
  // generate images
  System.Windows.Forms.DataVisualization.Charting.Chart oCh = new();
  oCh.SaveImage(filePath, System.Drawing.Imaging.ImageFormat.Gif);

  // fetch image
  FileStream content = new FileStream(filePath, 
  FileMode.Open, FileAccess.Read, FileShare.None, 4096, options: FileOptions.DeleteOnClose);

  // File stream will be disposed after response is sent
  var re = this.File(content, contentType, filename);

  return re;
}
KaraNoKara
  • 85
  • 10
  • For very big files, you are going to need to use a stream and read it chunks at a time via a loop. – beautifulcoder Mar 21 '23 at 21:09
  • 1
    @beautifulcoder the framework deals with that, although there are file-specific download methods available that can be more efficient (in http.sys/is mode, for example, they can offload the file IO to kernel-mode directly) – Marc Gravell Mar 21 '23 at 21:15
  • ASP.NET Core by-default _requires_ all IO to be async, but you aren't using `FileStream`'s `useAsync:` constructor - so I'm wondering if that's playing a part. Also, using `FileOptions.DeleteOnClose` in this situation is just asking for trouble. – Dai Mar 22 '23 at 01:44
  • Hmm, `FileOptions.DeleteOnClose`? - [I'm getting deja-vu...](https://stackoverflow.com/q/75800066/159145) – Dai Mar 22 '23 at 01:44
  • @Dai, This is not a problem, even I don't use it (don't delete file after sent), the response still not be fulfilled. Also, it doesn't matter whether to use `useAsync` since I only use 1 thread. – KaraNoKara Mar 22 '23 at 01:56
  • @KaraNoKara _"since I only use 1 thread"_ - that's not what `useAsync` means, and while your `SendFile` action is a synchronous method the rest of ASP.NET Core's plumbling _is_ very async-heavy (i.e. there is _no way_ your application is only using 1 thread overall: at a minimum the CLR reserves ~20 threads just for the initial `ThreadPool` during startup). – Dai Mar 22 '23 at 01:59
  • Sorry, Guys, I found out what the problem is, Please see edited detail! – KaraNoKara Mar 22 '23 at 18:04

0 Answers0