Reading a binary file and using Response.BinaryWrite()

后端 未结 10 1901
既然无缘
既然无缘 2020-11-28 12:16

I have an app that needs to read a PDF file from the file system and then write it out to the user. The PDF is 183KB and seems to work perfectly. When I use the code at th

相关标签:
10条回答
  • 2020-11-28 12:20

    Please read this before using Response.TransmitFile: http://improve.dk/blog/2008/03/29/response-transmitfile-close-will-kill-your-application

    0 讨论(0)
  • 2020-11-28 12:20

    Maybe you are missing a Response.close to close de Binary Stream

    0 讨论(0)
  • 2020-11-28 12:22

    Just for future reference, as stated in this blog post: http://blogs.msdn.com/b/aspnetue/archive/2010/05/25/response-end-response-close-and-how-customer-feedback-helps-us-improve-msdn-documentation.aspx

    It is not recommended to call Response.Close() or Response.End() - instead use CompleteRequest().

    Your code would look somewhat like this:

        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();
    
    0 讨论(0)
  • 2020-11-28 12:28

    In addition to Igor's Response.Close(), I would add a Response.Flush().

    0 讨论(0)
  • 2020-11-28 12:30

    Since you're sending the file directly from your filesystem with no intermediate processing, why not use Response.TransmitFile instead?

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

    (I suspect that your problem is caused by a missing Response.End, meaning that you're sending the rest of your page's content appended to the PDF data.)

    0 讨论(0)
  • 2020-11-28 12:30

    In my MVC application, I have enabled gzip compression for all responses. If you are reading this binary write from an ajax call with gzipped responses, you are getting the gzipped bytearray rather than original bytearray that you need to work with.

    //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('<a/>');
        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 }); " This will give you that invalid/corrupt file that you are trying to open when you turn that byte array into a file in your javascript if you don't uncompress it first.

    To fix this, you have a choice to either prevent gzipping this binary data so that you can properly turn it into the file that you are downloading, or you have to decompress that gzipped data in your javascript code before you turn it into a file.

    0 讨论(0)
提交回复
热议问题