该问题适用于任何执行MVC 或MVVM 的JavaScript 框架。上面提到的:
我需要将敲除生成的 DOM 作为字符串传递,
到我的 C# 控制器中,这样我就可以构建 PDF。
所以我将使用一个简单的工作示例来在 ASP.NET MVC 中完成这项工作。以前从未使用过knockout.js,所以要获取DOM 元素并使用jQuery 发送Ajax 请求。
视图,基于您上面引用的示例:1. 获取outerHTML of ul; 2. 向控制器发送Ajax 请求:
<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>
}
注意事项:
-
FileSaver.js 在技术上不是必需的,但可以节省大量时间,而不必处理不同的浏览器实现。参考Browser compatibility。
-
BinaryTransport is 如果使用
jQuery 是必需的 - 遗憾的是框架 doesn't support this feature 我上次检查时开箱即用。 AngularJS 等其他框架确实支持二进制。参考Sending and Receiving Binary Data。
jquery-binary.js 是一个简单 jQuery 插件我为几个内部项目写的:
(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));
和控制器:1.用XMLWorkerHelper解析HTML字符串; 2. 返回 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();
}
会让你决定如何处理内联样式。 ;)