我正在尝试从大约5000个表单列表中创建一个单独的pdf文档,这些表单是用我用C#编写的ASP.NET MVC网站中的对象列表标记的。一旦我执行大约1500个表单的冲压过程,我就会得到一个Out of Memory Exception。如果我将对象列表限制在1500个以下的对象中,我就不会收到错误。
这是模仿表单数据的数据对象:
public class MyPageData
{
public string Name { get; set; }
public string Description { get; set; }
public decimal DueAmount { get; set; }
public decimal PaidAmount { get; set; }
}
创建文档的代码。注意模板是pdf格式,Stream是使用写访问权限创建的FileStream对象,无文件共享。
public class DocumentBuilder
{
public static void FillDocument(IList<MyPageData> pages, string template, Stream outputFile)
{
using (Document document = new Document())
{
using (PdfSmartCopy copy = new PdfSmartCopy(document, outputFile))
{
document.Open();
foreach (var page in pages)
{
PdfReader reader = new PdfReader(StampPage(template, page));
copy.AddPage(copy.GetImportedPage(reader, 1));
copy.FreeReader(reader);
}
}
}
}
private static byte[] StampPage(string template, MyPageData page)
{
PdfReader reader = new PdfReader(template);
using (MemoryStream stream = new MemoryStream())
{
using (PdfStamper stamper = new PdfStamper(reader, stream))
{
AcroFields fields = stamper.AcroFields;
FillFields(fields, page);
stamper.FormFlattening = true;
stamper.Writer.Flush();
}
return stream.ToArray();
}
}
private static void FillFields(AcroFields fields, MyPageData page)
{
fields.SetField("Name", page.Name);
fields.SetField("Description", page.Description);
fields.SetField("DueAmount", page.DueAmount.ToString());
fields.SetField("PaidAmout", page.PaidAmount.ToString());
}
}
我已经遍及iText和iTextSharp文档了,我相信我的代码是正确的。我确实试图按照演示Here来压缩文档,但是在标记时仍会抛出错误。有什么想法或建议吗?
答案 0 :(得分:1)
(尚未回答)
我刚尝试使用以下代码运行5,000代码而没有问题。第一个块创建一个匹配您的模板,第二个块填充您的类的一些示例数据,第三个块实际实现您的逻辑。您的代码与此之间有什么截然不同的东西吗?这会给你一个OOM例外吗?
//Creates our sample template
var templateFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "template.pdf");
using (var fs = new FileStream(templateFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
var fields = new string[] { "Name", "Description", "DueAmount", "PaidAmout" };
var y = 700;
foreach (var f in fields) {
var tf = new TextField(writer, new iTextSharp.text.Rectangle(100, y, 400, y + 50), f);
writer.AddAnnotation(tf.GetTextField());
y -= 200;
}
doc.Close();
}
}
}
//Create our final PDF
var pages = new List<MyPageData>();
for (decimal i = 0; i < 5000; i++) {
pages.Add(new MyPageData() { Name = "Chris", Description = "Cheese", DueAmount = i, PaidAmount = i * 0.5m });
}
//Create our file
var outputFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "output.pdf");
using (var fs = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
DocumentBuilder.FillDocument(pages, templateFile, fs);
}
修改强>
我将它增加到75个字段,虽然需要更长的时间,但仍然没有得到OOM。为了进行测试,我将您的MyPageData
课程更改为:
public class MyPageData {
public string[] StringData { get; set; }
}
您的DocumentBuilder
FillFields
来:
private static void FillFields(AcroFields fields, MyPageData page) {
var fieldCount = 75;
for (var j = 0; j < fieldCount; j++) {
fields.SetField("Field_" + j.ToString(), page.StringData[j]);
}
}
我的模板和示例数据创建到:
var fieldCount = 75;
//Creates our sample template
var templateFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "template.pdf");
using (var fs = new FileStream(templateFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
var y = 800;
//Create 75 fields
for (var j = 0; j < fieldCount; j++) {
var tf = new TextField(writer, new iTextSharp.text.Rectangle(100, y, 400, y + 10), "Field_" + j.ToString());
tf.Options = tf.Options | TextField.MULTILINE;
writer.AddAnnotation(tf.GetTextField());
y -= 10;
}
doc.Close();
}
}
}
//Create our sample data
var pages = new List<MyPageData>();
for (decimal i = 0; i < 5000; i++) {
var stringData = new List<string>();
for (var j = 0; j < fieldCount; j++) {
stringData.Add("Data_" + j.ToString());
}
pages.Add(new MyPageData() { StringData = stringData.ToArray() });
}