所以你也愿意考虑其他客户?听起来您有一个儿童绘画应用程序,并且想要生成一些可以保留他们当时绘画状态的东西。
让我们面对现实吧,XML 并不是那么高效。这不是它的目的。它是机器和人类可读、可验证等的。
<Canvas>
相反,一个以 JSON 格式将画布状态提交给服务器的基于网页的网页怎么样(更少的字节,构建它们的工作也更少)。然后,服务器可以使用它想要的任何地狱库/语言工作。大量的 JSON->my-language 库漂浮在那里。
您在 PDF 库中的选择仅受您在服务器上安装的内容的限制。你还说你想尽可能少地读/写。
最有效的可能设置是将只读部分 PDF 加载到内存中,以最大限度地减少画布更改(包括图像)的影响。每个会话都会复制该部分 PDF,将 JSON 转换为 PDF 图形命令,然后保存 PDF。
为了最大限度地减少对 PDF 的结构更改,您需要使用内联图像。PDF 中没有新对象意味着您根本不需要更改交叉引用表(直到您添加字体或想要重用现有图像)。您可以构建“文档信息”字典,并在对象之间填充特定数量的空格,这样您就可以在不更改任何字节偏移量的情况下填充它(这将迫使您重新计算外部参照表)。
您可能需要也可能不需要弄乱页面大小......我们只是在这里谈论一页,对吧?
所以PDF看起来像......
%%PDF-1.6
<3-4 random high order bytes to convince folks that we're a binary stream>
1 0 obj
<</Type/Catalog/Pages 2 0 R>>
endobj
2 0 obj
<</Type/Pages/Count 1/Kids[3 0 R]>>
endobj
3 0 obj
<</Type/Page/Contents 4 0 R/MediaBox[0 0 612 792]/Parent 2 0 R>>
endobj
5 0 obj
<</Type/DocInfo/Author() --<insert big whitespace gap here>--
/Title() --<ditto>--
/Subject() --<ditto>--
/Keywords() --<ditto>--
/Creator(My app's Name)
/Producer(My pdf library's name)
/CreationDate(encodedDateWhenThisTemplateWasBuilt) D:YYYYMMDDHHMMSS-timeZoneOffset
/ModDate() --<another, smaller whitespace gap>--
>>
4 0 obj
<</Filter/SeveralDifferentFiltersAvailable/Length --<byte length of the stream in this file>-->>
stream
你的模板就停在那里。你会有一个类似的“PDF 结尾”模板,看起来像这样:
endstream
endobj
xref
0 6
0000000000 65535 f
0000000010 00000 n
0000000025 00000 n
0000000039 00000 n
0000000097 00000 n
0000000050 00000 n
trailer
<</Root 1 0 R/Size 6/Info 5 0 R>>
startxref
--<some white space>--
%%EOF
最后的数字列都是错误的。第一列是该特定对象的字节偏移量(我现在不打算计算字节,谢谢)。第二列在很大程度上无关紧要。
PDF 填写应用程序需要知道:
- 您打算在第一个模板中填写的所有内容的字节偏移量。
- 顺便说一下,所有“文档信息”字段都是可选的。/Info 键和它指向的字典是可选的。如果你愿意的话,你可以拉他们。
- 内容流的 /Length 键。这需要是流本身的过滤后字节长度。
- 如何将 JSON 转换为 pdf 绘图命令。如果您想作弊,您可以使用 iText[Sharp] 的 PdfContentByte 类,使用它的绘图命令,然后获取完成的字节流并将其添加到您的 PDF 中。确保您使用内联图像,否则整个方案都会出现在窗外。如果您觉得需要,可能还有其他类似的库。或者,您可以阅读 PDF 规范并自行编写。您将坚持使用相当有限的 PDF 内容语法子集。
- 单词“xref”从文件开头的字节偏移量。您可以计算:LengthOfInitialTemplate + LengthOfContentStream + OffsetFromStartOf2ndTemplateTo'xref'。
- “startxref”下方行的字节偏移量,这是您写入“xref”的预先计算的字节偏移量的地方
你不会比这更有效率。你曾经读过你的模板。读取/计算一次您需要的字节偏移量。