Prerequisite
- Basic C# coding knowledge
- Minimum knowledge of Web API
- Understanding for the REST service
When we are working with REST service, it is very important to understand how to send files. In this article, we are going to discuss how to return files (PDF/Word/Excel) from Web API service.
I am going to explain a step by step process to transfer a file over Http REST service.
Let’s assume we have a requirement to send a file based on the file type provided to the service request. For example, when we send the file type as PDF, service will return PDF file if we send Doc, service will return Word document. (I have taken this sample to cover all types of files).
We cannot send the file from its original state. To send the file to REST service, we have to follow the below steps.
Convert the Required file into Bytes
Initially, we have to convert the file into bytes using File Class (which is from System.IO)
//converting Pdf file into bytes array
var dataBytes = File.ReadAllBytes(reqBook);
Adding bytes to MemoryStream
Now, create an instance of MemoryStream by passing the byte form of the file.
//adding bytes to memory stream
var dataStream = new MemoryStream(dataBytes);
Adding MemoryStream object to the HttpResponseMessage Content
The final step is to add the MemoryStream object to the HttpResponseMessage Content as follows.
httpResponseMessage.Content = new StreamContent(bookStuff);
Other Mandatory Changes for HttpResponseMessage Headers
We are returning a file here so, to make the client understand the content of the service, we have to modify the following HttpResponseMessage header properties.
- ContentDisposition
- FileName
- ContentType
Following code is used to implement the above 3 fields.
httpResponseMessage.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
httpResponseMessage.Content.Headers.ContentDisposition.FileName = PdfFileName;
httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
We need to talk about the ContentType here. I have used application/octet-stream, whereas in some places, we can see application/pdf, but why I have used it? In a simple way, I can say that when we are sending a file to the REST service and we don’t know the file type but it is a trusted one, in these situations, we have to use application/octet-stream.
Complete Code in a single shot
I have written with IHttpActionResult and HttpResponseMessage action results.
public class EbookController : ApiController
{
string bookPath_Pdf = @"C:\MyWorkSpace\SelfDev\UserAPI\UserAPI\Books\sample.pdf";
string bookPath_xls = @"C:\MyWorkSpace\SelfDev\UserAPI\UserAPI\Books\sample.xls";
string bookPath_doc = @"C:\MyWorkSpace\SelfDev\UserAPI\UserAPI\Books\sample.doc";
string bookPath_zip = @"C:\MyWorkSpace\SelfDev\UserAPI\UserAPI\Books\sample.zip";
[HttpGet]
[Route("Ebook/GetBookFor/{format}")]
public IHttpActionResult GetbookFor(string format)
{
string reqBook = format.ToLower() == "pdf" ? bookPath_Pdf : (format.ToLower() == "xls" ? bookPath_xls : (format.ToLower() == "doc" ? bookPath_doc : bookPath_zip));
string bookName = "sample." + format.ToLower();
//converting Pdf file into bytes array
var dataBytes = File.ReadAllBytes(reqBook);
//adding bytes to memory stream
var dataStream = new MemoryStream(dataBytes);
return new eBookResult(dataStream, Request, bookName);
}
[HttpGet]
[Route("Ebook/GetBookForHRM/{format}")]
public HttpResponseMessage GetBookForHRM(string format)
{
string reqBook = format.ToLower() == "pdf" ? bookPath_Pdf : (format.ToLower() == "xls" ? bookPath_xls : (format.ToLower() == "doc" ? bookPath_doc : bookPath_zip));
string bookName = "sample." + format.ToLower();
//converting Pdf file into bytes array
var dataBytes = File.ReadAllBytes(reqBook);
//adding bytes to memory stream
var dataStream = new MemoryStream(dataBytes);
HttpResponseMessage httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK);
httpResponseMessage.Content = new StreamContent(dataStream);
httpResponseMessage.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
httpResponseMessage.Content.Headers.ContentDisposition.FileName = bookName;
httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
return httpResponseMessage;
}
}
public class eBookResult : IHttpActionResult
{
MemoryStream bookStuff;
string PdfFileName;
HttpRequestMessage httpRequestMessage;
HttpResponseMessage httpResponseMessage;
public eBookResult(MemoryStream data, HttpRequestMessage request, string filename)
{
bookStuff = data;
httpRequestMessage = request;
PdfFileName = filename;
}
public System.Threading.Tasks.Task<HttpResponseMessage> ExecuteAsync(System.Threading.CancellationToken cancellationToken)
{
httpResponseMessage = httpRequestMessage.CreateResponse(HttpStatusCode.OK);
httpResponseMessage.Content = new StreamContent(bookStuff);
//httpResponseMessage.Content = new ByteArrayContent(bookStuff.ToArray());
httpResponseMessage.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
httpResponseMessage.Content.Headers.ContentDisposition.FileName = PdfFileName;
httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
return System.Threading.Tasks.Task.FromResult(httpResponseMessage);
}
}
Result
I ran the project and tried to download all the books in all formats with the following URLs (your IP may change when you run the code on your system).
- http://localhost:59217/api/Ebook/GetBookFor?format=pdf
- http://localhost:59217/api/Ebook/GetBookFor?format=doc
- http://localhost:59217/api/Ebook/GetBookFor?format=xls
- http://localhost:59217/api/Ebook/GetBookFor?format=zip
Initially, I have sent the PDF format value to the service and got the PDF file in response.

Later, I requested the Word document.

How to execute the attached source code (Please go through this section if you want to practice this article with the attached project)
I have attached only required files with the actual folder structure (due to the size of the project).
Please follow the below steps to create the file transferrable Web API service.
- Download the attached project.
- Open Visual Studio and create New Web API project.
- Create Book folder at root level in the project.
- Add any sample pdf, word, excel, zip (name them as sample) files into it.

- Create a new API controller and Copy the content of EbookController from the downloaded project into it.
- Please change the books path strings in newly created Controllers.
- Add the following code to WebAPIConfig.cs
config.Routes.MapHttpRoute( name: "FileServiceRoute”, routeTemplate: “api / {controller}/{action}/ {id}”, defaults: new {id = RouteParameter.Optional} ); - Rebuild the project and run.
- Run any of the above URLs with your project IP
You can see downloading of files when you run the URLs.

balasubramanyam subramanyamPosted Sep 15, 2020, 4:08 AM
Do you have program to save file from octet stream to mp4
satyanarayana kokkuPosted Aug 8, 2019, 3:21 AM
File is currupting when i click on download link of file in ui of api please help me
Aj RamPosted May 16, 2019, 10:12 AM
Good Post! I got a question, how to download a video file. I got a URL to webapi which return a Video(.Avi) file, i want to save that file to local. much apprecaited for any suggestion. cheers.
alan mathewPosted Mar 19, 2019, 2:48 AM
Hai sir, After using the code i am able to download files successfully but pages are empty. How can i solve the problem string reqBook = "test.pdf"; var path = Path.Combine( Directory.GetCurrentDirectory(), "wwwroot", $"resources/{ reqBook}"); string bookName = "test.pdf"; //converting Pdf file into bytes array var dataBytes = System.IO.File.ReadAllBytes(path); //adding bytes to memory stream var dataStream = new MemoryStream(dataBytes); HttpResponseMessage httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK); httpResponseMessage.Content = new StreamContent(dataStream); httpResponseMessage.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment"); httpResponseMessage.Content.Headers.ContentDisposition.FileName = bookName; httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream"); return httpResponseMessage;
Raj BhupathiPosted Mar 16, 2019, 7:19 AM
Hi, I had copied the above code in my controller and ran it. While executing the above links in browser with my local host and local path for the files. I'm getting error as "The webpage cannot be found".
Oryza AnggaraPosted Dec 10, 2018, 6:36 AM
Hi, why would you use "httpResponseMessage.Content = new StreamContent(bookStuff); " instead of "//httpResponseMessage.Content = new ByteArrayContent(bookStuff.ToArray());" ? ..im failed using the first one when downloading files in zip (compressed into zip on the fly using ZipArchive class). When i use your commented one, my code is work. I want to know the reason, please advice
sunil patelPosted Nov 13, 2018, 2:23 AM
Content not showing in proper format while downloading the excel file.
Robert EverettPosted Sep 9, 2018, 3:23 PM
Would this work with .png and .jpg files ?
Ann RooneyPosted May 31, 2018, 6:19 AM
Thanks a mill - simply explained.
Arthur CaldeiraPosted May 24, 2018, 3:48 PM
Good post... It helped me a lot with to download file from a WebAPI using a VueJS front end. Thank You!
Sai MeinPosted Jan 25, 2018, 11:29 AM
I can download my pdf file. But no data did not show in my pdf file. plz help?
Eduardo NardiPosted Dec 27, 2017, 7:13 AM
Congratulations for your post !! Simple, efficient and very well explained !! It works fine !! PS..sorry my English !!!