C# 如何在线传输pdf
我正在使用itextSharp生成pdf文档这是我保存pdf的方式:C# 如何在线传输pdf,c#,pdf,itextsharp,itext,C#,Pdf,Itextsharp,Itext,我正在使用itextSharp生成pdf文档这是我保存pdf的方式: string file=“C:/MyDoc/FileName.pdf”。如果我在网络上运行这个程序,那么文件路径可能会有所不同。经过大量研究,我发现我可以做到: Response.ContentType = "application/pdf"; Response.AddHeader("content-disposition", "attachment;" + "filename=
string file=“C:/MyDoc/FileName.pdf”代码>。如果我在网络上运行这个程序,那么文件路径可能会有所不同。经过大量研究,我发现我可以做到:
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;" + "filename=FileName.pdf");
Response.Write(document);
Response.OutputStream.Flush();
Response.OutputStream.Close();
问题是如何在上面的代码中声明字符串文件
。这样做的原因是因为稍后我将页码插入到传递文件变量的pdf中,例如,我自己在生成Word/pdf文件时遇到一些问题。这些生成不适用于相对路径。我的解决方案如下(在VBA中,但在C#中应该类似):
创建文件信息
Dim getInfo As System.IO.FileInfo
用所需文件的(相对)路径填充fileinfo:
getInfo = My.Computer.FileSystem.GetFileInfo("Pathname")
使用fileinfo获取完整的绝对路径,而不是相对路径(getInfo.FullName)
我自己生成Word/PDF文件时遇到一些问题。这些生成不适用于相对路径。我的解决方案如下(在VBA中,但在C#中应该类似):
创建文件信息
Dim getInfo As System.IO.FileInfo
用所需文件的(相对)路径填充fileinfo:
getInfo = My.Computer.FileSystem.GetFileInfo("Pathname")
使用fileinfo获取完整的绝对路径,而不是相对路径(getInfo.FullName)
其中似乎没有任何内容依赖于物理文件的存在。在我看来,您应该能够创建一个内存流
,用它代替内存流
,然后将内存流的内容写入响应。在某些情况下,您甚至可以直接写入.OutputStream
(避免内存流
),但这取决于它是否需要查找等。但假设我们必须缓冲:
using(MemoryStream ms = new MemoryStream()) {
CreatePdf(ms); // uses this stream instead of new FileStream(...)
// not shown: set response headers
var data = ms.GetBuffer();
Response.OutputStream.Write(data, 0, (int)ms.Length);
}
其中似乎没有任何内容依赖于物理文件的存在。在我看来,您应该能够创建一个内存流
,用它代替内存流
,然后将内存流的内容写入响应。在某些情况下,您甚至可以直接写入.OutputStream
(避免内存流
),但这取决于它是否需要查找等。但假设我们必须缓冲:
using(MemoryStream ms = new MemoryStream()) {
CreatePdf(ms); // uses this stream instead of new FileStream(...)
// not shown: set response headers
var data = ms.GetBuffer();
Response.OutputStream.Write(data, 0, (int)ms.Length);
}
我只是想进一步说明马克的答案PdfWriter
和PdfStamper
都使用抽象类System.IO.Stream
。您发布的示例使用了System.IO.FileStream
和System.Web.HttpResponse.OutputStream
,这两个子类都是System.IO.Stream
。这两个是绝对有效的,但它们是最终的和专门的。还有另一个不太最终的子类,它在内存中工作,那就是System.IO.MemoryStream
您可以将PdfWriter
绑定到MemoryStream
,完成所有工作,然后说“给我一个表示PDF的字节数组”。然后,PdfReader
有一个构造函数重载,它接受一个字节数组,因此您可以直接将字节传递回该数组。因此,您可以说newpdfreader(bytes)
而不是newpdfreader(filepath)
我鼓励您在使用PDF时使用此模式:
创建一个MemoryStream
使用该流创建PDF
完成后获取原始字节
对字节做些什么。写入磁盘,发送到HttpResponse
,发送回步骤2,等等
前三个步骤的优点是,您不必考虑文件路径,甚至ASP.Net本身。该代码从桌面到服务器是100%可移植的。第四步是唯一一个真正针对特定情况的步骤,是“好的,我已经制作了一个PDF,现在我想用它做什么?”
请参阅下面的代码和注释,以获取演示此功能的示例:
//Instead of writing to a file, we're going to just keep a byte array around
//that we can work with and/or write to something else
//At the start, this array is not initialized to anything
Byte[] bytes;
//Create a very basic PDF using a MemoryStream
using (var ms = new MemoryStream()) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, ms)) {
doc.Open();
doc.Add(new Paragraph("Hello World"));
doc.Close();
}
}
//When the "PDF stuff" is done but before we dispose of the MemoryStream, grab the raw bytes
bytes = ms.ToArray();
}
//At this exact point, the variable "bytes" is an array of bytes that
//represents a PDF. This could be sent to the browser via Response.BinaryWrite(bytes).
//It could also be written to disk using System.IO.File.WriteAllBytes(myFilePath, bytes).
//It could also be read back into a PdfReader directly via the code below
//Create a new PDF based on the old PDF
using (var ms = new MemoryStream()) {
//Bind a reader to our previously created array
using (var reader = new PdfReader(bytes)) {
//Very simple stamper, could be much more complex, just draws a rectangle
using (var stamper = new PdfStamper(reader, ms)) {
var cb = stamper.GetOverContent(1);
cb.Rectangle(50, 50, 200, 200);
cb.SetColorFill(BaseColor.RED);
cb.Fill();
}
}
//Once again, grab the bytes before closing the MemoryStream but after the "PDF stuff"
bytes = ms.ToArray();
}
//Once again, the "bytes" variable represents a PDF at this point
//The above can be repeated as many times as needed
我只是想进一步说明马克的答案PdfWriter
和PdfStamper
都使用抽象类System.IO.Stream
。您发布的示例使用了System.IO.FileStream
和System.Web.HttpResponse.OutputStream
,这两个子类都是System.IO.Stream
。这两个是绝对有效的,但它们是最终的和专门的。还有另一个不太最终的子类,它在内存中工作,那就是System.IO.MemoryStream
您可以将PdfWriter
绑定到MemoryStream
,完成所有工作,然后说“给我一个表示PDF的字节数组”。然后,PdfReader
有一个构造函数重载,它接受一个字节数组,因此您可以直接将字节传递回该数组。因此,您可以说newpdfreader(bytes)
而不是newpdfreader(filepath)
我鼓励您在使用PDF时使用此模式:
创建一个MemoryStream
使用该流创建PDF
完成后获取原始字节
对字节做些什么。写入磁盘,发送到HttpResponse
,发送回步骤2,等等
前三个步骤的优点是,您不必考虑文件路径,甚至ASP.Net本身。该代码从桌面到服务器是100%可移植的。第四步是唯一一个真正针对特定情况的步骤,是“好的,我已经制作了一个PDF,现在我想用它做什么?”
请参阅下面的代码和注释,以获取演示此功能的示例:
//Instead of writing to a file, we're going to just keep a byte array around
//that we can work with and/or write to something else
//At the start, this array is not initialized to anything
Byte[] bytes;
//Create a very basic PDF using a MemoryStream
using (var ms = new MemoryStream()) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, ms)) {
doc.Open();
doc.Add(new Paragraph("Hello World"));
doc.Close();
}
}
//When the "PDF stuff" is done but before we dispose of the MemoryStream, grab the raw bytes
bytes = ms.ToArray();
}
//At this exact point, the variable "bytes" is an array of bytes that
//represents a PDF. This could be sent to the browser via Response.BinaryWrite(bytes).
//It could also be written to disk using System.IO.File.WriteAllBytes(myFilePath, bytes).
//It could also be read back into a PdfReader directly via the code below
//Create a new PDF based on the old PDF
using (var ms = new MemoryStream()) {
//Bind a reader to our previously created array
using (var reader = new PdfReader(bytes)) {
//Very simple stamper, could be much more complex, just draws a rectangle
using (var stamper = new PdfStamper(reader, ms)) {
var cb = stamper.GetOverContent(1);
cb.Rectangle(50, 50, 200, 200);
cb.SetColorFill(BaseColor.RED);
cb.Fill();
}
}
//Once again, grab the bytes before closing the MemoryStream but after the "PDF stuff"
bytes = ms.ToArray();
}
//Once again, the "bytes" variable represents a PDF at this point
//The above can be repeated as many times as needed
您不会在其中显示任何需要物理文件的内容;如果您使用MemoryStream
而不是文件流
,它是否有效;您当前正在服务器上保存;这是一个非常糟糕的想法你没有显示任何需要物理文件的内容;如果您使用MemoryStream
而不是文件流
,它是否有效;您当前正在服务器上保存;那真是个好主意