Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RazorPDF save pdf file to server directory in MVC4

I am currently assembling and displaying a PDF using RazorPDF in MVC4 and would like to save the PDF file to the file system at the same time I return the view.

The following line of code in the controller action is calling the view:

return new PdfResult(claims, "PDF");
like image 203
Dan Aschmann Avatar asked Aug 09 '13 18:08

Dan Aschmann


2 Answers

I was able to finally write the pdf to the directory system by changing the code base of the RazorPDF render method. The Rendor method creates a PdfWriter object that is associated to the response stream:

        // Associate output with response stream
        var pdfWriter = PdfWriter.GetInstance(document, viewContext.HttpContext.Response.OutputStream);
        pdfWriter.CloseStream = false;

The solution was to create another PdfWriter object that was associated to a FileStream object as illustrated below:

        // Create the pdf file in the directory system
        var fileStream = new FileStream(myPdfFilePath, FileMode.Create);
        var pdfWriter2 = PdfWriter.GetInstance(document, fileStream);

I then closed the objects:

        fileStream.Close();

        pdfWriter.Close();
        pdfWriter2.Close();

I had to essentially incorporate the PdfResult and PdfView classes of RazorPDF into my own project and significantly alter the code. The reason is because I also had to encorporate calls to an email class that sent the pdf to a user.

The full Render method is displayed below:

    public void Render(ViewContext viewContext, TextWriter writer)
    {
        // generate view into string
        var sb = new System.Text.StringBuilder();
        TextWriter tw = new System.IO.StringWriter(sb);
        myResult.View.Render(viewContext, tw);
        var resultCache = sb.ToString();

        // detect itext (or html) format of response
        XmlParser parser;
        using (var reader = GetXmlReader(resultCache))
        {
            while (reader.Read() && reader.NodeType != XmlNodeType.Element)
            {
                // no-op
            }

            if (reader.NodeType == XmlNodeType.Element && reader.Name == "itext")
                parser = new XmlParser();
            else
                parser = new HtmlParser();
        }

        // Create a document processing context
        var document = new Document();
        document.Open();

        // Associate output with response stream
        var pdfWriter = PdfWriter.GetInstance(document, viewContext.HttpContext.Response.OutputStream);
        pdfWriter.CloseStream = false;

        // Create the pdf file in the directory system
        var fileStream = new FileStream(myPdfFilePath, FileMode.Create);
        var pdfWriter2 = PdfWriter.GetInstance(document, fileStream);

        // this is as close as we can get to being "success" before writing output
        // so set the content type now
        viewContext.HttpContext.Response.ContentType = "application/pdf";

        // parse memory through document into output
        using (var reader = GetXmlReader(resultCache))
        {
            parser.Go(document, reader);
        }

        fileStream.Close();

        // Send an email to the claimant
        Thread.Sleep(100);
        if (File.Exists(myPdfFilePath))
        {
            var subject = "PDF Documents";

            var body = Config.GetContent(ContentParams.CLAIM_DOCUMENT_EMAIL_BODY_TEXT);

            bool success;
            string errorMessage;

            Email.Send(myEmailAddress, subject, body, out success, out errorMessage, myPdfFilePath);
        }

        pdfWriter.Close();
        pdfWriter2.Close();

    }

It would be nice if this capability were somehow incorporated into the current RazorPDF project.

like image 141
Dan Aschmann Avatar answered Sep 21 '22 22:09

Dan Aschmann


why not just get the stream via a web request to the url?

string razorPdfUrl="http://...";
var req = HttpWebRequest.Create(RazorPDFURL);
using (Stream pdfStream = req.GetResponse().GetResponseStream())
{
    ...
}
like image 36
tony Avatar answered Sep 20 '22 22:09

tony