Generating PDFs using Phantom JS on .NET applications

I have been looking into phantomJS and looks like it could be a great tool to use generating PDFs. I wonder if anyone have successfully used it for their .NET applications.

My specific question is: how would you use modules like rasterize.js on the server, receive requests and send back generated pdfs as a response.

My general question is: is there any best practice for using phantomJS with .NET Applications. What would be the best way to achieve it?

I am fairly new in .NET World and I would appreciate the more detailed answers. Thanks everyone. 🙂

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

I don’t know about best practices, but, I’m using phantomJS with no problems with the following code.

public ActionResult DownloadStatement(int id)
{
    string serverPath = HttpContext.Server.MapPath("~/Phantomjs/");
    string filename = DateTime.Now.ToString("ddMMyyyy_hhmmss") + ".pdf";

    new Thread(new ParameterizedThreadStart(x =>
    {
        ExecuteCommand("cd " + serverPath + @" & phantomjs rasterize.js http://localhost:8080/filetopdf/" + id.ToString() + " " + filename + @" ""A4""");
    })).Start();

    var filePath = Path.Combine(HttpContext.Server.MapPath("~/Phantomjs/"), filename);

    var stream = new MemoryStream();
    byte[] bytes = DoWhile(filePath);

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

private void ExecuteCommand(string Command)
{
    try
    {
        ProcessStartInfo ProcessInfo;
        Process Process;

        ProcessInfo = new ProcessStartInfo("cmd.exe", "/K " + Command);
        ProcessInfo.CreateNoWindow = true;
        ProcessInfo.UseShellExecute = false;

        Process = Process.Start(ProcessInfo);
    }
    catch { }
}

public ViewResult FileToPDF(int id)
{
    var viewModel = file.Get(id);
    return View(viewModel);
}

private byte[] DoWhile(string filePath)
{
    byte[] bytes = new byte[0];
    bool fail = true;

    while (fail)
    {
        try
        {
            using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                bytes = new byte[file.Length];
                file.Read(bytes, 0, (int)file.Length);
            }

            fail = false;
        }
        catch
        {
            Thread.Sleep(1000);
        }
    }

    System.IO.File.Delete(filePath);
    return bytes;
}

Here is the action flow:

The user clicks on a link to DownloadStatement Action. Inside there, a new Thread is created to call the ExecuteCommand method.

The ExecuteCommand method is responsible to call phantomJS. The string passed as an argument do the following.

Go to the location where the phantomJS app is and, after that, call rasterize.js with an URL, the filename to be created and a print format. (More about rasterize here).

In my case, what I really want to print is the content delivered by the action filetoupload. It’s a simple action that returns a simple view. PhantomJS will call the URL passed as parameter and do all the magic.

While phantomJS is still creating the file, (I guess) I can not return the request made by the client. And that is why I used the DoWhile method. It will hold the request until the file is created by phantomJS and loaded by the app to the request.

Method 2

If you’re open to using NReco.PhantomJS, which provides a .NET wrapper for PhantomJS, you can do this very succinctly.

public async Task<ActionResult> DownloadPdf() {
    var phantomJS = new PhantomJS();
    try {
        var temp = Path.Combine(Path.GetTempPath(),
            Path.ChangeExtension(Path.GetRandomFileName(), "pdf")); //must end in .pdf
        try {
            await phantomJS.RunAsync(HttpContext.Server.MapPath("~/Scripts/rasterize.js"),
                new[] { "https://www.google.com", temp });
            return File(System.IO.File.ReadAllBytes(temp), "application/pdf");
        }
        finally {
            System.IO.File.Delete(temp);
        }
    }
    finally {
        phantomJS.Abort();
    }
}

Method 3

Here’s some very basic code to generate a PDF using Phantom.JS but you can find more information here: https://buttercms.com/blog/generating-pdfs-with-node

var webPage = require('webpage');
var page = webPage.create();

page.viewportSize = { width: 1920, height: 1080 };
page.open("http://www.google.com", function start(status) {
page.render('google_home.pdf, {format: 'pdf', quality: '100'});
phantom.exit();
});


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x