0

I am trying to create a print PDF file for my project.

Here is my code

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult PrintPdf(SubmitReport model)
    {
        if (model == null)
        {
            throw new ArgumentNullException(nameof(SubmitReport));
        }

        var pdfModel = new PdfViewModel {HeaderImgUrl = AppDomain.CurrentDomain.BaseDirectory + @"Content\logo.jpg"};
        var pdfStream = new MemoryStream(PdfGenerator.PayrollConfirmPdf(pdfModel).ToArray());

        // TODO: what is the name of the pdf file?
        var filename = string.Concat("PayrollConfirmation", DateTime.Now.ToString("yyyyMMddHHmmss"), ".pdf");

        return File(pdfStream, "application/pdf", filename);            
    }

It seems everything works fine, but after the function return, nothing happen. I was expecting a PDF file open/download in my local machine. However, no pop-up show up (as if nothing happen).

Any ideas?

Thanks in advance.

2
  • Check output of pdfStream, is that returns byte array containing PDF file? Also try this: var pdfStream = new MemoryStream(PdfGenerator.PayrollConfirmPdf(pdfModel)).ToArray();. Commented Apr 26, 2018 at 1:47
  • @TetsuyaYamamoto Yes, I forced it to be byte array: byte[] pdfStream; var stream = new MemoryStream(); using (stream) { stream = PdfGenerator.PayrollConfirmPdf(pdfModel); pdfStream = stream.ToArray(); } The problem still there. Commented Apr 26, 2018 at 18:47

1 Answer 1

2

Seems that this line messing up:

var pdfStream = new MemoryStream(PdfGenerator.PayrollConfirmPdf(pdfModel).ToArray());

This creates instance of MemoryStream from a byte array, which possibly FileResult starts reading from end of stream instead of beginning.

You can use one of 2 possible solutions below:

1) Convert MemoryStream from PayrollConfirmPdf method as byte array and return the PDF as FileContentResult:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult PrintPdf(SubmitReport model)
{
    // other stuff

    byte[] pdfStream;

    using (var stream = new MemoryStream())
    {
        // fill stream content from other source
        stream = PdfGenerator.PayrollConfirmPdf(pdfModel);
        pdfStream = stream.ToArray();
    }

    // TODO: what is the name of the pdf file?
    var filename = string.Concat("PayrollConfirmation", DateTime.Now.ToString("yyyyMMddHHmmss"), ".pdf");

    // FileContentResult
    return File(pdfStream, "application/pdf", filename);            
}

2) Return FileStreamResult with Seek method set to beginning of stream:

using (var stream = new MemoryStream())
{
    // fill stream content from other source
    // make sure that PayrollConfirmPdf return MemoryStream here!
    stream = PdfGenerator.PayrollConfirmPdf(pdfModel);

    // add this line when using memory stream
    // alternative 1: stream.Seek(0, 0);
    stream.Seek(0, SeekOrigin.Begin); 

    var filename = string.Concat("PayrollConfirmation", DateTime.Now.ToString("yyyyMMddHHmmss"), ".pdf");

    // FileStreamResult
    return File(stream, "application/pdf", filename);
}   

Note that you can use stream.Position = 0; to reset stream position if stream.Seek method doesn't work.

Side note:

Since MemoryStream implements IDisposable, you should use using statement to dispose the stream immediately.

Similar issues:

FileResult with MemoryStream gives empty result .. what's the problem?

Return file for Saving from HttpPost Asp.Net MVC method (if using AJAX POST to download the file)

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for your answer, I tried to use the IDisposable. I got an error: "Severity Code Description Project File Line Suppression State Error CS1656 Cannot assign to 'stream' because it is a 'using variable'"
Once again, thank you for your detailed answer. I also tried your solution #1. I can verify that the steam has content. However, it still behaves the same. The same problem still there.
I dug a little bit. The main problem is in the front-end. Because I am using an AJAX post, and the pdf file is successfully generated. I just need to let the front-end grab the file.
If you're using AJAX POST, then you should use success block to ensure that the response received and use window.location.href to redirect into GET action method which returns FileResult (AJAX primarily used to sending request while stay on same page).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.