Return PDF to browser using Asp.net core

I created a Wep API in the ASP.Net core to return a PDF. Here is my code:

public HttpResponseMessage Get(int id) { var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK); var stream = new System.IO.FileStream(@"C:\Users\shoba_eswar\Documents\REquest.pdf", System.IO.FileMode.Open); response.Content = new StreamContent(stream); response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment"); response.Content.Headers.ContentDisposition.FileName = "NewTab"; response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf"); return response; } 

But it only returns a JSON response:

 { "version":{ "major":1, "minor":1, "build":-1, "revision":-1, "majorRevision":-1, "minorRevision":-1 }, "content":{ "headers":[ { "key":"Content-Disposition", "value":[ "attachment; filename=NewTab" ] }, { "key":"Content-Type", "value":[ "application/pdf" ] } ] }, "statusCode":200, "reasonPhrase":"OK", "headers":[ ], "requestMessage":null, "isSuccessStatusCode":true } 

Am I doing something wrong here?

+10
source share
3 answers

As explained in ASP.NET Core, HTTPRequestMessage returns a strange JSON message , ASP.NET Core does not support returning HttpResponseMessage (which package did you install to access this type?).

Because of this, the serializer simply writes all the output properties of the HttpResponseMessage to the output, as it would with any other unsupported response type.

To support custom responses, you must return IActionResult -implementing. There are many of them . In your case, I would look in FileStreamResult :

 public IActionResult Get(int id) { var stream = new FileStream(@"path\to\file", FileMode.Open); return new FileStreamResult(stream, "application/pdf"); } 

Or just use PhysicalFileResult , where the stream is processed for you:

 public IActionResult Get(int id) { return new PhysicalFileResult(@"path\to\file", "application/pdf"); } 

Of course, all this can be simplified by using helper methods such as Controller.File() :

 public IActionResult Get(int id) { var stream = new FileStream(@"path\to\file", FileMode.Open); return File(stream, "application/pdf", "FileDownloadName.ext"); } 

This simply abstracts the creation of a FileContentResult or FileStreamResult (the latter for this overload).

Or, if you are converting an old MVC application or web API and don’t want to convert all your code at once, add a link to WebApiCompatShim (NuGet) and wrap your current code in a ResponseMessageResult :

 public IActionResult Get(int id) { var response = new HttpResponseMessage(HttpStatusCode.OK); var stream = ... response.Content... return new ResponseMessageResult(response); } 

If you do not want to use return File(fileName, contentType, fileDownloadName) , then FileStreamResult does not support setting the content-disposition header from the constructor or through properties.

In this case, you will have to add the response header to the answer yourself before returning the result of the file:

 var contentDisposition = new ContentDispositionHeaderValue("attachment"); contentDisposition.SetHttpFileName("foo.txt"); Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString(); 
+38
source

I can not comment on the answer of CodeCaster, as my reputation is not high enough. Upon attempt

 public IActionResult Get(int id) { using (var stream = new FileStream(@"path\to\file", FileMode.Open)) { return File(stream, "application/pdf", "FileDownloadName.ext"); } } 

we got

ObjectDisposedException: Unable to access the remote object. Object Name: "Unable to access private file." System.IO.FileStream.BeginRead (byte [] array, int offset, int numBytes, AsyncCallback callback, object state)

We removed the usage

  [HttpGet] [Route("getImageFile")] public IActionResult GetWorkbook() { var stream = new FileStream(@"pathToFile", FileMode.Open); return File(stream, "image/png", "image.png"); } 

And it worked. This is ASP.NET Core 2.1 running in IIS Express.

+6
source

I don't have enough reputation to post this as a comment, so I am posting as an answer. The first 3 solutions from @CodeCaster and the solution from @BernhardMaertl are correct.

However, for those who may not work with files often (for example, I), keep in mind that if the process executing this code (for example, API) has only read permissions for the file, you will need to specify this as the third parameter when creating your FileStream , otherwise, by default, the file is opened for reading / writing, and you will get an exception, since you do not have write permissions.

A third solution from @CodeCaster would look like this:

 public IActionResult Get(int id) { var stream = new FileStream(@"path\to\file", FileMode.Open, FileAccess.Read); return File(stream, "application/pdf", "FileDownloadName.ext"); } 
0
source

Source: https://habr.com/ru/post/1012142/


All Articles