Lectura de un archivo binario y uso de Response.BinaryWrite ()

Tengo una aplicación que necesita leer un archivo PDF del sistema de archivos y luego escribirlo para el usuario. El PDF tiene 183 KB y parece funcionar perfectamente. Cuando uso el código en la parte inferior, el navegador obtiene un archivo de 224 KB y recibo un mensaje de Acrobat Reader que dice que el archivo está dañado y no se puede reparar.

Aquí está mi código (también he intentado usar File.ReadAllBytes (), pero obtengo lo mismo):

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); } 

Prueba agregar

Response.End ();

después de la llamada a Response.BinaryWrite ().

Es posible que inadvertidamente esté enviando otro contenido después de Response.BinaryWrite, lo que puede confundir al navegador. Response.End se asegurará de que el navegador solo obtenga lo que realmente desea.

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

Esto funciona para nosotros Creamos archivos PDF de SQL Reporting Services.

Hemos usado esto con mucho éxito. WriteFile hace la descarga por usted y un Flush / End al final para enviarlo todo al cliente.

  //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(); 

Ya que está enviando el archivo directamente desde su sistema de archivos sin procesamiento intermedio, ¿por qué no usar Response.TransmitFile lugar?

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

(Sospecho que su problema está causado por la falta de Response.End , lo que significa que está enviando el rest del contenido de su página adjuntado a los datos PDF).

Solo para referencia futura, como se indica en esta publicación del blog: http://blogs.msdn.com/b/aspnetue/archive/2010/05/25/response-end-response-close-and-how-customer-feedback- helps-us-improve-msdn-documentation.aspx

No se recomienda llamar a Response.Close() o Response.End() ; en su lugar, utilice CompleteRequest() .

Tu código se vería algo así:

  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(); 

Tal vez te está faltando un Response.close para cerrar de Binary Stream

En mi aplicación MVC, he habilitado la compresión gzip para todas las respuestas. Si estás leyendo esta escritura binaria de una llamada ajax con respuestas gzip, obtienes el archivo gzipped bytearray en lugar del original bytearray con el que tienes que trabajar.

 //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});” Esto le dará ese archivo inválido / corrupto que está tratando de abrir cuando convierta ese conjunto de bytes en un archivo en su javascript si no lo descomprimes primero.

Para solucionarlo, tiene la opción de evitar la compresión de estos datos binarios para que pueda convertirlos correctamente en el archivo que está descargando, o tiene que descomprimir esos datos comprimidos en su código JavaScript antes de convertirlo en un archivo.

Además de Response.Close () de Igor, agregaría un Response.Flush ().

También me pareció necesario agregar lo siguiente:

 Response.Encoding = Encoding.Default 

Si no incluí esto, mi JPEG estaba dañado y duplicaba el tamaño en bytes.

Pero solo si el controlador regresaba de una página ASPX. Parecía funcionar desde una ASHX, esto no era necesario.