In this article, we are going to learn how to return a file in an ASP.NET Core Web API and some concepts behind it. That said, we are going to implement a simple Web API to read a local file and return this file to download.
Let’s start it.
VIDEO: How to Return a File From a Web API.
What is a MIME type?
Before we get to the code, we need to understand a couple of concepts to work with files on the internet.
Once file extensions have no meaning for the web, the MIME Type (Multipurpose Internet Mail Extensions), is responsible for representing the nature and the format of a document we want to transmit over the internet.
The MIME Type structure consists of a type, a slash separator, and a subtype.
For this article, we are going to return a .png image, that said, we are going to use image/png as MIME Type to define our file.
It is good to mention that, application/octet-stream is a default MIME Type in case we need to return an unknown file.
To learn more about the most common MIME Types, check the Common MIME Types article.
About Byte Array and Stream
In C#, we can represent binary data (a file, an image, or anything else stored on our computer) using byte[] or Stream instance.
A byte array (byte[]) is a simple array of bytes (unsigned 8-bit integer) containing the bytes of the file.
Stream is an abstract class to represent a sequence of bytes. The most common class that derives from Stream is FileStream and MemoryStream.
You can check the Convert Byte Array to File in C# article to learn more about byte arrays and the C# Back to Basics – Files, StreamWriter and StreamReader to learn more about Stream.
Web API Controller Preparation
Once we have an ASP.NET Core Web API ready, let’s create an empty API Controller:
[Route("api/[controller]")]
[ApiController]
public class DownloadsController : ControllerBase
{
private readonly IFileService _fileService;
private const string MimeType = "image/png";
private const string FileName = "CM-Logo.png";
public DownloadsController(IFileService fileService)
{
_fileService = fileService;
}
}
Note that we have a _fileService, a MimeType, and a FileName field. The _fileService contains the logic to transform the file into a byte array or a stream. For this article, we are not going into detail about how to do it, however, you can check the FileService class implementation in our source code.
The MimeType field represents the nature of the file we want to return and the FileName represents a suggestion file name to download.
Return a File in ASP.NET Core Web API As a ByteArray
Now, let’s create our first ReturnByteArray action to return a file using Byte Array:
[HttpGet("images-byte")]
public IActionResult ReturnByteArray()
{
var image = _fileService.GetImageAsByteArray();
return File(image, MimeType, FileName);
}
Note that this is an images-byte route with the Get HTTP Verb. Once we are using the same file result for every request, we don’t need any input parameter.
So, first, we use GetImageAsByteArray() from the FileService class to retrieve the image we want to return as an array of bytes.
Then, we return a call to the File method passing the image file as a byte array, the mimeType we set as a class field, and the file name we want to return, as parameters.
The File method lives under the ControllerBase abstract class and returns a FileContentResult, which is responsible to provide the file to download.
Return a File in Web API As a Stream
Now, let’s create a ReturnStream action:
[HttpGet("images-stream")]
public IActionResult ReturnStream()
{
var image = _fileService.GetImageAsStream();
return File(image, MimeType, FileName);
}
We are going to keep the Get HTTP Verb, but this time, we set our route to images-stream.
This action is similar to the one in which we are using byte[] with the exception that, now, we are calling the GetImageAsStream() method from the FileService class.
Finally, we return a call to the File method. Note that this time we are passing a Stream object instead of a byte[] as the first parameter. This is possible because the File method has many overloads.
Downloading The File
Now that our code is ready, let’s check the behavior against when we are using swagger, postman, and the browser.
Using Swagger
Once we run the Web API application, we can see our two routes in Swagger:
/api/Downloads/images-byte /api/Downloads/images-stream
Let’s call the images-byte route and check the result:
Now, let’s execute the images-stream route:
As we can see, in both cases we received an HTTP Status Code 200 as a result, indicating success and, as a response body, a link to download the image.
Checking the Result Using Postman
Let’s check the behavior when we make requests via Postman:
As we can see, different from Swagger, Postman doesn’t provide us a link or open the dialog box to download the image. Instead, it shows the image in its body response.
Browser
When we call any route (images-byte or images-stream) the browser downloads the image into the default download folder or opens the dialog box to indicate which folder we want to save the file.
Conclusion
In this article, besides learning some concepts behind how the web handles files, we have seen how to return a file using Asp.Net Core Web API. Also, we have checked how swagger, postman, and browser behave when we request a file in a Web API.





what about memory leak ?
[HttpGet("images-stream")] public IActionResult ReturnStream() { var image = _fileService.GetImageAsStream(); return File(image, MimeType, FileName); }Hi, this is the official statement from Microsoft:
Of course, this is valid if your comment was related to this.
Any links highly appreciated …
Hi. If you think about that quote, this is the link:https://learn.microsoft.com/en-us/dotnet/api/system.io.memorystream?view=net-7.0#remarks
IFileService returns Stream not MemoryStream. It is very prone to errors when you just change the implementation. I think one extra word “using” does not make the example hard to understand.
Yes, but the implementation of the method works with MemoryStream. But ok, adding the using keyword won’t hurt anyone.
so FileStreamResultExecutor will make it but it is worth to mention that since it is not obvious.
Where’s this magical File() coming from?
Hi James. I am not sure why is it magical, but if you inspect our source code, which you can find at the top of each of our articles, you will find the method inside the controller: https://github.com/CodeMazeBlog/CodeMazeGuides/blob/main/aspnetcore-webapi/ReturnFileWebApi/ReturnFileWebApi/Controllers/DownloadsController.cs
As you can return NotFound, BadRequest, or OK from an action inside the controller, you can return File as well.
It’s magical because it only belongs to MVC not WebAPI controllers and it’s a function inherited not imported.
Well, James, you asked where this method is coming from and I just assumed that you don’t know (just by reading the article) how we use this method and how we access it. So, I gave you the simple answer. Now, if you go that deep into the Microsoft.AspNetCore.Mvc, you will find the ControllerBase class, which contains all the methods that I mentioned in my reply. Since each controller inherits that ControllerBase class, this is also part of the Web API project.
But at this point, I am not sure what was the point of your initial question.
Right. Sorry if I seemed frustrated; I was not; I said that with a smile. Everything you said is correct. This just does not apply to WebAPI users. You might make that clear to the readers, but I seem to be the only stupid one here. In another coincidence, there was an error in a middleware that we have which I did not write, but I see that someone else had the same error, so I assume both came from the same code sample that was copied. When I implemented the WebAPI version, the error presented itself, and I didn’t know which way was up or down. Answers to my question with hundreds of upvotes didn’t work for me until I fixed the issue with the middleware.
I couldn’t find the link to
“How to consume this API in client application”
Please help
I am not sure that I understand. What link are you referring to?
How retrieve image as part of json endpoint in webapi 2 asp.net?
Thanks for sharing.
see how to consume this service from angular.
From this moment I thank you for your answer.
You can read more about it here: https://code-maze.com/download-files-dot-net-core-angular/