创建 pdf 类型的 Memorystream 并返回浏览器

问题描述

我必须创建一个带有简单文本消息的空白 PDF 并将其返回到浏览器。我不必使用任何第三方 PDF 库,如 iTextSharp、PDFDocument 等。

我正在使用 MemoryStream,但生成的 PDF 已损坏。

 MemoryStream ms = new MemoryStream();
 ms.Write(System.Text.Encoding.Unicode.GetBytes("test message"),System.Text.Encoding.Unicode.GetBytes("test message").Length);
 response.addheader("Content-disposition","attachment;filename=" + id.ToString() + ".pdf");
 return File(ms.ToArray(),"application/pdf");

我缺少什么?

解决方法

您基本上已经创建了一个 TXT 文件并将其发送到浏览器,将其声明为 PDF。

PDF 有自己的文件格式。 PDF 1.2 等旧版本的 PDF 标准可以用类似文本的格式编写。 Wayback Machine has a copy of the PDF 1.2 specification

您可能希望受益于较新版本的 PDF 标准。也许您不想花时间阅读和理解 400 页。此外,您不需要庞大的字符串模板,而是需要一种更具表现力的创建 PDF 文件的方式。因此,图书馆可以为您节省大量时间和精力。

无论如何,您可以阅读该规范并提出类似的内容

string template = @"
%PDF-1.2 
4 0 obj << >> 
stream 
BT/ 12 Tf({0})' ET 
endstream 
endobj
3 0 obj << /Type /Page /Parent 2 0 R /Contents 4 0 R >> endobj
2 0 obj << /Kids [3 0 R ] /Count 1 /Type /Pages /MediaBox [ 0 0 99 99 ] >> endobj
1 0 obj << /Pages 2 0 R /Type /Catalog >> endobj
trailer << /Root 1 0 R >>
%%EOF
";
string text = "Text message";
string pdf = string.Format(template,text);

它有:

  • 第 5.2 章中描述的 %PDF-1.2 标头
  • 第 4 章中描述的各种对象
  • << >> 中的字典,如第 4.7 章所述
  • streamendstream 之间的流,如第 4.8 章所述
  • 一个文本对象,以 BT 开头并以 ET 结尾,如图 8.1 中所述
  • 使用 Tf 操作文本字体,如第 8.7.3 章所述
  • () 之间的文本字符串,如第 4.4 章所述。我在这里使用了 .NET {0} 占位符。
  • 具有所需 MediaBox 的页面定义页面大小,如第 6.4 章所述
  • 第 5.5 章中描述的 trailer,以 %%EOF 结尾,包含一个强制性的 /Root 条目。

您有点“自下而上”阅读此 PDF。预告片指的是对象1 0,它指的是页面2 0,它指的是一页3 0,它指的是内容4 0