如何正确地提供PDF文件

我使用的是.NET 3.5 ASP.NET。 目前,我的网站以下列方式提供PDF文件:

context.Response.WriteFile(@"c:\blah\blah.pdf");

这很好用。 但是,我想通过context.Response.Write(char [], int, int)方法来提供它。

所以我尝试通过发送文件

 byte [] byteContent = File.ReadAllBytes(ReportPath); ASCIIEncoding encoding = new ASCIIEncoding(); char[] charContent = encoding.GetChars(byteContent); context.Response.Write(charContent, 0, charContent.Length); 

这没用(例如浏览器的PDF插件抱怨文件已损坏)。

所以我尝试了Unicode方法:

 byte [] byteContent = File.ReadAllBytes(ReportPath); UnicodeEncoding encoding = new UnicodeEncoding(); char[] charContent = encoding.GetChars(byteContent); context.Response.Write(charContent, 0, charContent.Length); 

这也没用。

我错过了什么?

您不应该将字节转换为字符,这就是它变为“损坏”的原因。 即使ASCII字符以字节存储,实际的ASCII字符集也限制为7位。 因此,使用ASCIIEncoding转换字节流将有效地从每个字节中删除第8位。

应将字节写入Response实例的OutputStream流。

而不是从文件中预先加载所有可能消耗大量内存的字节,从流中读取块中的文件是一种更好的方法。 这是一个如何从一个流读取然后写入另一个流的示例:

 void LoadStreamToStream(Stream inputStream, Stream outputStream) { const int bufferSize = 64 * 1024; var buffer = new byte[bufferSize]; while (true) { var bytesRead = inputStream.Read(buffer, 0, bufferSize); if (bytesRead > 0) { outputStream.Write(buffer, 0, bytesRead); } if ((bytesRead == 0) || (bytesRead < bufferSize)) break; } } 

然后,您可以使用此方法将文件的内容直接加载到Response.OutputStream

 LoadStreamToStream(fileStream, Response.OutputStream); 

更好的是,这是一个打开文件并将其内容加载到流的方法:

 void LoadFileToStream(string inputFile, Stream outputStream) { using (var streamInput = new FileStream(inputFile, FileMode.Open, FileAccess.Read)) { LoadStreamToStream(streamInput, outputStream); streamInput.Close(); } } 

您可能还需要通过执行以下操作来设置ContentType:

 Response.ContentType = "application/octet-stream"; 

在Peter Lillevold的回答的基础上,我去了,并为他的上述function做了一些扩展方法。

 public static void WriteTo(this Stream inputStream, Stream outputStream) { const int bufferSize = 64 * 1024; var buffer = new byte[bufferSize]; while (true) { var bytesRead = inputStream.Read(buffer, 0, bufferSize); if (bytesRead > 0) { outputStream.Write(buffer, 0, bytesRead); } if ((bytesRead == 0) || (bytesRead < bufferSize)) break; } } public static void WriteToFromFile(this Stream outputStream, string inputFile) { using (var inputStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read)) { inputStream.WriteTo(outputStream); inputStream.Close(); } }