读取二进制文件并使用Response.BinaryWrite()

我有一个应用程序需要从文件系统中读取PDF文件,然后将其写出给用户。 PDF为183KB,似乎完美无缺。 当我使用底部的代码时,浏览器获取一个224KB的文件,我从Acrobat Reader收到一条消息,说文件已损坏且无法修复。

这是我的代码(我也尝试过使用File.ReadAllBytes(),但我得到了相同的东西):

using (FileStream fs = File.OpenRead(path)) { int length = (int)fs.Length; byte[] buffer; using (BinaryReader br = new BinaryReader(fs)) { buffer = br.ReadBytes(length); } Response.Clear(); Response.Buffer = true; Response.AddHeader("content-disposition", String.Format("attachment;filename={0}", Path.GetFileName(path))); Response.ContentType = "application/" + Path.GetExtension(path).Substring(1); Response.BinaryWrite(buffer); } 

尝试添加

到Response.End();

在调用Response.BinaryWrite()之后。

您可能无意中在Response.BinaryWrite之后发回其他内容,这可能会混淆浏览器。 Response.End将确保浏览器只获得您真正想要的内容。

  Response.BinaryWrite(bytes); Response.Flush(); Response.Close(); Response.End(); 

这对我们有用。 我们从SQL Reporting Services创建PDF。

我们使用它取得了很大的成功。 WriteFile为您下载,最后一个Flush / End将其全部发送给客户端。

  //Use these headers to display a saves as / download //Response.ContentType = "application/octet-stream"; //Response.AddHeader("Content-Disposition", String.Format("attachment; filename={0}.pdf", Path.GetFileName(Path))); Response.ContentType = "application/pdf"; Response.AddHeader("Content-Disposition", String.Format("inline; filename={0}.pdf", Path.GetFileName(Path))); Response.WriteFile(path); Response.Flush(); Response.End(); 

由于您直接从文件系统发送文件而没有中间处理,为什么不使用Response.TransmitFile呢?

 Response.Clear(); Response.ContentType = "application/pdf"; Response.AddHeader("Content-Disposition", "attachment; filename=\"" + Path.GetFileName(path) + "\""); Response.TransmitFile(path); Response.End(); 

(我怀疑您的问题是由于缺少Response.End引起的,这意味着您将页面的其余内容发送到PDF数据中。)

仅供将来参考,如本博文中所述: http : //blogs.msdn.com/b/aspnetue/archive/2010/05/25/response-end-response-close-and-how-customer-feedback-帮助-US-提高-MSDN-documentation.aspx

建议不要调用Response.Close()Response.End() – 而是使用CompleteRequest()

您的代码看起来有点像这样:

  byte[] bytes = {}; bytes = GetBytesFromDB(); // I use a similar way to get pdf data from my DB Response.Clear(); Response.ClearHeaders(); Response.Buffer = true; Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.ContentType = "application/pdf"; Response.AppendHeader("Content-Disposition", "attachment; filename=" + anhangTitel); Response.AppendHeader("Content-Length", bytes.Length.ToString()); this.Context.ApplicationInstance.CompleteRequest(); 

请在使用Response.TransmitFile之前阅读此内容: http : //improve.dk/blog/2008/03/29/response-transmitfile-close-will-kill-your-application

也许你错过了关闭de Binary Stream的Response.close

在我的MVC应用程序中,我为所有响应启用了gzip压缩。 如果您正在使用gzip响应从ajax调用中读取此二进制写入,那么您将获得gzipped bytearray而不是需要使用的原始bytearray。

 //c# controller is compressing the result after the response.binarywrite [compress] public ActionResult Print(int id) { ... var byteArray=someService.BuildPdf(id); return return this.PDF(byteArray, "test.pdf"); } //where PDF is a custom actionresult that eventually does this: public class PDFResult : ActionResult { ... public override void ExecuteResult(ControllerContext context) { //Set the HTTP header to excel for download HttpContext.Current.Response.Clear(); //HttpContext.Current.Response.ContentType = "application/vnd.ms-excel"; HttpContext.Current.Response.ContentType = "application/pdf"; HttpContext.Current.Response.AddHeader("content-disposition", string.Concat("attachment; filename=", fileName)); HttpContext.Current.Response.AddHeader("Content-Length", pdfBytes.Length.ToString()); //Write the pdf file as a byte array to the page HttpContext.Current.Response.BinaryWrite(byteArray); HttpContext.Current.Response.End(); } } //javascript function pdf(mySearchObject) { return $http({ method: 'Post', url: '/api/print/', data: mySearchObject, responseType: 'arraybuffer', headers: { 'Accept': 'application/pdf', } }).then(function (response) { var type = response.headers('Content-Type'); //if response.data is gzipped, this blob will be incorrect. you have to uncompress it first. var blob = new Blob([response.data], { type: type }); var fileName = response.headers('content-disposition').split('=').pop(); if (window.navigator.msSaveOrOpenBlob) { // for IE and Edge window.navigator.msSaveBlob(blob, fileName); } else { var anchor = angular.element(''); anchor.css({ display: 'none' }); // Make sure it's not visible angular.element(document.body).append(anchor); // Attach to document anchor.attr({ href: URL.createObjectURL(blob), target: '_blank', download: fileName })[0].click(); anchor.remove(); } }); 

}

“var blob = new Blob([response.data],{type:type});”这将为您提供当您将该字节数组转换为javascript中的文件时尝试打开的无效/损坏文件不要先解压缩它。

要解决此问题,您可以选择阻止对此二进制数据进行gzipping,以便您可以将其正确地转换为正在下载的文件,或者在将其转换为文件之前必须在javascript代码中解压缩该gzip压缩数据。

除了Igor的Response.Close()之外,我还要添加一个Response.Flush()。

我还发现有必要添加以下内容:

 Response.Encoding = Encoding.Default 

如果我没有包含这个,我的JPEG已损坏并且以字节为单位加倍。

但仅当处理程序从ASPX页面返回时。 它似乎从ASHX运行,这不是必需的。