Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return ActionResult (file) from class that does not derive from Controller?

I have two download file methods, so I wanted to extract part which actually hits the disk to some helper/service class, but I struggle with returning that file to controller and then to user

How can I return from class that does not derives from Controller a file with that easy-to-work method from Mvc.ControllerBase.File?

public (bool Success, string ErrorMessage, IActionResult File) TryDownloadFile(string FilePath, string FriendlyName)
{
    try
    {
        var bytes = File.ReadAllBytes(FilePath);

        if (FilePath.EndsWith(".pdf"))
        {
            return (true, "", new FileContentResult(bytes, "application/pdf"));
        }
        else
        {
            return (true, "", ControllerBase.File(bytes, "application/octet-stream", FriendlyName));
        }
    }
    catch (Exception ex)
    {
        return (false, ex.Message, null); 
    }
}

The error is

An object reference is required for the non-static field, method, or property 'ControllerBase.File(Stream, string, string)'

for this line:

return (true, "", ControllerBase.File(bytes, "application/octet-stream", FriendlyName));

Is there any possibility to achieve that?

like image 529
Joelty Avatar asked Feb 12 '19 10:02

Joelty


2 Answers

ControllerBase.File is just a convenience method that creates an instance of FileContentResult for you. Here's the actual code that gets used:

new FileContentResult(fileContents, contentType) { FileDownloadName = fileDownloadName };

You can simply take that code and use it in your class, like this:

return (
    true,
    "",
    new FileContentResult(bytes, "application/octet-stream") { FileDownloadName = FriendlyName });
like image 53
Kirk Larkin Avatar answered Oct 19 '22 22:10

Kirk Larkin


If you see what ControllerBase does, you can replicate that: https://github.com/aspnet/AspNetCore/blob/c1bc210e8ebb6402ac74f4705d5748bc8e3ee544/src/Mvc/src/Microsoft.AspNetCore.Mvc.Core/ControllerBase.cs#L1120.

public virtual FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName)
    => new FileContentResult(fileContents, contentType) { FileDownloadName = fileDownloadName };

So create a FileContentResult with your parameters and return it from the action.

like image 1
juunas Avatar answered Oct 19 '22 22:10

juunas