Home > database >  How to return FileStreamResult outside of the main controller?
How to return FileStreamResult outside of the main controller?

Time:12-27

I was downloading a pdf file in the main controller with the help of FileStreamResult like this and the file got dowmloaded just fine:

public FileStreamResult Download(Invoice? invoice)
{
    // Create new document.
    ComponentInfo.SetLicense("FREE-LIMITED-KEY");
    var document = new PdfDocument();
    
    // Add page.
    var page = document.Pages.Add();
    static bool IsNotNull([NotNullWhen(true)] object? invoice) => invoice != null;

    var rectangle = page.Content.Elements.AddPath();
    
    rectangle.AddRectangle(new PdfPoint(25, 650),
        new PdfSize(273, 150));
    var rectangleFormat = rectangle.Format;
    
    rectangleFormat.Stroke.IsApplied = true;
    rectangleFormat.Stroke.Width = 1;
    rectangleFormat.Stroke.Color = PdfColor.FromGray(0.5);

    var rectangle2 = page.Content.Elements.AddPath();

    rectangle2.AddRectangle(new PdfPoint(300, 650),
        new PdfSize(273, 150));
    var rectangleFormat2 = rectangle2.Format;

    rectangleFormat2.Stroke.IsApplied = true;
    rectangleFormat2.Stroke.Width = 1;
    rectangleFormat2.Stroke.Color = PdfColor.FromGray(0.5);


    // Save PDF file.
    var stream = new MemoryStream();
    document.Save(stream);
    stream.Position = 0;

    // Download file.
    return File(stream, mimeType, fileName);
}

But then I tried to put this download function in a seperate file and inject it with dependency injection:

public void Download(Invoice? invoice)
{
    genPdf.GeneratePdf(this, mimeType, fileName, invoice);
}

And now in the new file the Return File() gives an error : Non-invocable member 'File' cannot be used like a method

public class GeneratePdf : IGeneratePdf
{
    FileStreamResult IGeneratePdf.GeneratePdf(ControllerBase controller,
        string mimeType, string fileName, Invoice? invoice)
    {
        // Create new document.
        ComponentInfo.SetLicense("FREE-LIMITED-KEY");
        var document = new PdfDocument();
        
        // Add page.
        var page = document.Pages.Add();
        static bool IsNotNull([NotNullWhen(true)] object? invoice) => invoice != null;

        var rectangle = page.Content.Elements.AddPath();

        rectangle.AddRectangle(new PdfPoint(25, 650),
            new PdfSize(273, 150));
        var rectangleFormat = rectangle.Format;
    
        rectangleFormat.Stroke.IsApplied = true;
        rectangleFormat.Stroke.Width = 1;
        rectangleFormat.Stroke.Color = PdfColor.FromGray(0.5);
        
        var rectangle2 = page.Content.Elements.AddPath();
    
        rectangle2.AddRectangle(new PdfPoint(300, 650),
            new PdfSize(273, 150));
        var rectangleFormat2 = rectangle2.Format;

        rectangleFormat2.Stroke.IsApplied = true;
        rectangleFormat2.Stroke.Width = 1;
        rectangleFormat2.Stroke.Color = PdfColor.FromGray(0.5);
    
        // Save PDF file.
        var stream = new MemoryStream();
        document.Save(stream);
        stream.Position = 0;
    
        // Download file.
        return File(stream, mimeType, fileName);
    }
}

I tried to make the new GeneratePdf inherit from base Controller class and I tried to call the File() method on the ControllerBase controller but the file still didn't get downloaded. Any other idea on how to fix that and keep the controller and the GeneratePdf functionality seperate?

CodePudding user response:

Non-invocable member 'File' cannot be used like a method

This error appears due to the fact the File on your GeneratePdf is in fact a Example Error

You can rectify your code by returning a Stream from the GeneratePdf and do a return File(..) on your controller instead.

public class GeneratePdf : IGeneratePdf
{
    Stream IGeneratePdf.GeneratePdf(Invoice? invoice)
    {
        .... //code omitted to safe space
        
        // Save PDF file.
        var stream = new MemoryStream();
        document.Save(stream);
        stream.Position = 0;

        // Download file.
        return stream;
    }
}

Then on the controller, do it this way:

public FileStreamResult Download(Invoice? invoice)
{
    return File(genPdf.GeneratePdf(invoice), mimeType, fileName);
}

Note that we return FileStreamResult just like your original code. This way controller is only concerned with how to present the data into end user.

I'm surprised after 15 hours theres no answer/progress on this QA.

  • Related