简体   繁体   中英

Returning a PDF from an ASP.NET Core 2 Controller

I am trying to return a PDF file from my ASP.NET Core 2 controller. I have this code (mostly borrowed from this SO question ):

var net = new System.Net.WebClient();
//a random pdf file link
var fileLocation = "https://syntera.io/documents/T&C.pdf";/
var data = net.DownloadData(fileLocation);
MemoryStream content = null;
try
{
    content = new MemoryStream(data);
    return new FileStreamResult(content, "Application/octet-stream");
}
finally
{
    content?.Dispose();
}

This code above is part of a service class that my controller calls. This is the code from my controller.

public async Task<IActionResult> DownloadFile(string fileName)
{
    var result = await _downloader.DownloadFileAsync(fileName);
    return result;
}

But I keep getting ObjectDisposedException: Cannot access a closed Stream.

The try and finally block was an attempt to fix it , from another SO question .

The main question is A) Is this the right way to send a PDF file back to the browser and B) if it isn't, how can I change the code to send the pdf to the browser?

Ideally , I don't want to first save the file on the server and then return it to the controller. I'd rather return it while keeping everything in memory.

The finally will always get called ( even after the return ) so it will always dispose of the content stream before it can be sent to the client, hence the error.

Ideally , I don't want to first save the file on the server and then return it to the controller. I'd rather return it while keeping everything in memory.

Use a FileContentResult class to take the raw byte array data and return it directly.

FileContentResult : Represents an ActionResult that when executed will write a binary file to the response.

async Task<IActionResult> DownloadFileAsync(string fileName){
    using(var net = new System.Net.WebClient()) {
        byte[] data = await net.DownloadDataTaskAsync(fileName);
        return new FileContentResult(data, "application/pdf") {
            FileDownloadName = "file_name_here.pdf"
        };
    }
}

No need for the additional memory stream

You must specify :

Response.AppendHeader("content-disposition", "inline; filename=file.pdf");
return new FileStreamResult(stream, "application/pdf")

For the file to be opened directly in the browser.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM