Using iTextSharp with knockout JavaScript or other MVC / MVVM framework?

前端 未结 1 1681
野趣味
野趣味 2021-01-27 08:55

Ok, since I did find out that I can use iTextSharp to generate a PDF, I went that route.

I\'ve got it to where it will save HTML with basic formatting to a PDF. That\'s

相关标签:
1条回答
  • 2021-01-27 09:33

    The question applies to any JavaScript Framework that does MVC or MVVM. Mentioned above:

    I need to pass the DOM that was generated by knockout, as a string, into my C# controller, so that I can build the PDF.

    So am going to go with a simple working example to get this done in ASP.NET MVC. Never used knockout.js before, so going to get the DOM element and send Ajax request with jQuery.

    The view, based on the example you referenced above: 1. Gets outerHTML of ul; 2. sends an Ajax request to the controller:

    <h4>People</h4>
    <ul id='wanted' data-bind="foreach: people">
        <li>
            Name at position <span data-bind="text: $index"> </span>:
            <span data-bind="text: name"> </span>
            <a href="#" data-bind="click: $parent.removePerson">Remove</a>
        </li>
    </ul>
    <button data-bind="click: addPerson">Add</button>
    <button data-bind="click: getPdf">Get PDF</button>
    
    @section scripts
    {
    <script src="~/Scripts/libs/knockout-3.4.0.js"></script>
    <script src="~/Scripts/ajax/FileSaver.js"></script>
    <script src="~/Scripts/ajax/jquery.binarytransport.js"></script>
    <script src="~/Scripts/ajax/jquery-binary.js"></script>
    <script type="text/javascript">
        function AppViewModel() {
            var self = this;
    
            self.getPdf = function (data, event) {
                $(this).downloadFile(
                    '@Url.Action("Index", "DomToPdf")',
                    { xHtml: $('#wanted').prop('outerHTML') }
                );
            }
    
            self.people = ko.observableArray([
                { name: 'Bert' },
                { name: 'Charles' },
                { name: 'Denise' }
            ]);
            self.addPerson = function () {
                self.people.push({ name: "New at " + new Date() });
            };
            self.removePerson = function () {
                self.people.remove(this);
            }
        }
        ko.applyBindings(new AppViewModel());
    </script>
    }
    

    Notes:

    1. FileSaver.js isn't technically required, but saves a great deal of time not having to deal with different browser implementations. Reference Browser compatibility.
    2. BinaryTransport is required if using jQuery - sadly the framework doesn't support this feature out of the box last I checked. Other frameworks like AngularJS do support binary. Reference Sending and Receiving Binary Data.

    jquery-binary.js is a simple jQuery Plugin I wrote for a couple of internal projects:

    (function ($) {
        $.fn.downloadFile = function(url, data, requestType) {
            $.ajax({
                url: url,
                data: data,
                type: requestType || 'POST',
                dataType: 'binary'
            })
            .done(function(data, textStatus, jqXHR) {
                var type = jqXHR.getResponseHeader('Content-Type');
                var filename = jqXHR.getResponseHeader('Content-Disposition');
                filename = filename && filename.indexOf('attachment') > -1
                    ? filename.replace(/(?:[^=])+=/, '')
                    : 'file.bin';
                var blob = new Blob([data], { type: type });
                saveAs(blob, filename);
            })
            .fail(function(jqXHR, textStatus, errorThrown) {
                alert(errorThrown);
            })
            ;
            return false;
        };
    }(jQuery));
    

    And the controller: 1. parses the HTML string with XMLWorkerHelper; 2. returns the PDF.

    [HttpPost]  // some browsers have URL length limits
    [ValidateInput(false)] // or throws HttpRequestValidationException
    public ActionResult Index(string xHtml)
    {
        Response.ContentType = "application/pdf";
        Response.AppendHeader(
            "Content-Disposition", "attachment; filename=test.pdf"
        );
        using (var stringReader = new StringReader(xHtml))
        {
            using (Document document = new Document())
            {
                PdfWriter writer = PdfWriter.GetInstance(
                    document, Response.OutputStream
                );
                document.Open();
                XMLWorkerHelper.GetInstance().ParseXHtml(
                    writer, document, stringReader
                );
            }
        }
    
        return new EmptyResult();
    }
    

    Will let you decide how to deal with the inline styles. ;)

    0 讨论(0)
提交回复
热议问题