Background Color:
 
Background Pattern:
Reset
Search
Home Recent Changes Show All Pages

Generation Options

Not Rated Yet

In this article we are going to demonstrate how easy it is to create our PDF file, and how we can save that PDF to many places (a standard file, a web response, and even as binary data).

 

Article contents

 

Setting the scene

 

If you are using Visual Studio for your development, make sure you have installed the scryber VSIX extension. Then within your solution add a new Scryber Document from the Add new Item dialog, called HelloWorld.pdfx

If you aren't using Visual Studio, then you can download the Scryber nuget package, and reference the dlls and schemas within there. And add a new XML file called HelloWorld.pdfx into your editor of choice.

See VSIX Deployment and Nuget Package for more information

 

Creating the template content

 

Once we have our template file, and before we can start outputting any PDF file, we need to create the document content. Let's just create a simple one pager.

 

	<?xml version="1.0" encoding="utf-8" ?>
	<pdf:Document xmlns:pdf="Scryber.Components, Scryber.Components, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
	              xmlns:styles="Scryber.Styles, Scryber.Styles, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe">
	  <Pages>

	    <pdf:Page styles:margins="10pt" >
	      <Content>
	        Hello World
	      </Content>
	    </pdf:Page>

	  </Pages>
	</pdf:Document>

 

And then we need to get that template loaded as an actual instance in our code.

 

    public void ProcessHelloWorld()
    {
        using (PDFDocument doc = PDFDocument.ParseDocument("[PathtoFile]/HelloWorld.pdfx"))
        {

        }
    }

 

Using code instead

We could just have easily created this document in code. But as documents become more complex this can become cumbersome and harder to maintain.

 

    public PDFDocument GenerateHelloWorld()
    {
        PDFDocument doc = new PDFDocument();

        PDFPage pg = new PDFPage();
        doc.Pages.Add(pg);
        pg.Style.Margins.All = 10;

        PDFLabel lbl = new PDFLabel();
        lbl.Text = "Hello World";
        pg.Contents.Add(lbl);

        return doc;
    }

    public void ProcessHellowWorldCode()
    {
        using (PDFDocument doc = this.GenerateHelloWorld())
        {

        }
    }

 

It is also possible to mix methods as needed to add dynamic content or new components

 

Save to a file

 

The simplest way to generate this document and save it to a file is to use one of the available ProcessDocument overloads.

 

    public void ProcessHelloWorld()
    {
        using (PDFDocument doc = PDFDocument.ParseDocument("[PathtoFile]/HelloWorld.pdfx"))
        {
            doc.ProcessDocument("[LocalPath]/HelloWorld.pdf");
        }
    }

 

And that is it (ignoring any exception handling our fail over procedure). Invoking the ProcessHelloWorld() method will generate the final PDF and save it to the specified path. The path can be relative or absolute and the current user must have permissions to write to that location.

 

[IMAGE OUTPUT HelloWorld.pdf]

 

 

 

There are is also an overload to allow overwriting if the file already exists at that path.

 

    public void ProcessHelloWorld()
    {
        using (PDFDocument doc = PDFDocument.ParseDocument("[PathtoFile]/HelloWorld.pdfx"))
        {
            doc.ProcessDocument("[LocalPath]/HelloWorld.pdf", System.IO.FileMode.Create);
        }
    }

 

Output to the HttpResponse

 

A key driver for the scryber library was that it would work with forms applications and web applications, with no change to the libraries or templates.

With this in mind we can easily create a handler to a ASP.NET button click in a web project to create and output out pdf file.

 

    protected void Generate_Click(object sender, EventArgs e)
    {
        string path = "HelloWorld.pdfx";
        path = Server.MapPath(path);

        using (PDFDocument doc = PDFDocument.ParseDocument(path))
        {
            doc.ProcessDocument(this.Response);
        }
    }

 

By passing in the current HTTPResponse, the method will automatically clear any content from the response, set the content type, set the output as an attachment with the name of the template (if there is one) and end the response once the document processing has completed.

We can also specify a different name than the name of the template using one of the overloads. Ending the response as required.

 

    protected void Generate_Click(object sender, EventArgs e)
    {
        string path = "HelloWorld.pdfx";
        path = Server.MapPath(path);

        using (PDFDocument doc = PDFDocument.ParseDocument(path))
        {
            doc.ProcessDocument(this.Response, "MyDocumentName.pdf", true);
        }
    }

 

There are in total 4 overloads to the ProcessDocument method that accept the HTTPResponse as the first argument, all with more and more parameters, so you can tailor the generation to whatever level is required. Ultimately they all call the primary overload method.

 

    using (PDFDocument doc = PDFDocument.ParseDocument(path))
    {
        string documentname = "Any Document name.pdf";
        bool asAttachment = true;
        bool clearContent = true;
        string contentType = "application/pdf";
        System.Text.Encoding encoding = System.Text.Encoding.ASCII;
        bool databind = true;
        bool endresponse = true;

        //call primary method with all options to generate the response
        doc.ProcessDocument(this.Response, documentname, asAttachment, clearContent,
                            contentType, encoding, databind, endresponse);
    }

 

Output to a stream

 

If we don't want to save directly to a response, or file - for example we want to cache the generated document or push it to a database or other data repository, then we can Process the document to a Stream and do whatever is required afterwards.

 

    string path = "HelloWorld.pdfx";
    path = Server.MapPath(path);

    byte[] data;
    using (PDFDocument doc = PDFDocument.ParseDocument(path))
    {
        using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
        {
            doc.ProcessDocument(ms);
            data = ms.ToArray();
        }
    }

    SaveMyBinaryPDF(data);

 

Customising the lifecycle

 

In all the examples we have called the ProcessDocument method to generate our PDF. In actual fact this method is a wrapper on the PDFDocument class for the complete lifecycle of the scryber Document Processing stages.

It is important that each of these stages are completed, but they can be executed independently in a number of ways. The following 3 methods are equivalent

    protected void SimpleProcessDocument(string template, string output)
    {
        using (PDFDocument doc = PDFDocument.ParseDocument(template))
        {
            doc.ProcessDocument(output);
        }
    }

    protected void ExtendedProcessDocument(string template, string output, bool bind)
    {
        using (PDFDocument doc = PDFDocument.ParseDocument(template))
        {
            doc.InitializeAndLoad();

            if (bind)
                doc.DataBind();

            doc.RenderToPDF(output, System.IO.FileMode.Create);
        }
    }

    protected void FullProcessDocument(string template, string output, bool bind)
    {
        using (PDFDocument doc = PDFDocument.ParseDocument(template))
        {
            PDFTraceLog log = PDFTraceContext.GetLog();
            PDFItemCollection items = doc.Items;

            //Initialize
            PDFInitContext init = new PDFInitContext(items,log);
            doc.Init(init);

            //Load
            PDFLoadContext load = new PDFLoadContext(items,log);
            doc.Load(load);

            // optional bind
            if (bind)
                doc.DataBind();

            //final render
            doc.RenderToPDF(output, System.IO.FileMode.Create);
        }
    }
It is possible to split the Layout and Render into separate methods too, but not recommended. The real benefit for splitting the process is to add dynamic content, alter item collections, or control the databinding explicitly.

 

See Also



  Rating
Rate This Page: Poor Great   |  Rate Content |
Average rating:  No Ratings Yet   
Number of Ratings : 0
  Comments
Add Comment
No Comments Yet