代码之家  ›  专栏  ›  技术社区  ›  jhunter

读取二进制文件并使用response.binarywrite()。

  •  20
  • jhunter  · 技术社区  · 15 年前

    我有一个应用程序需要从文件系统中读取一个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);
    }
    
    10 回复  |  直到 6 年前
        1
  •  22
  •   BarneyHDog    15 年前

    尝试添加

    响应。

    在调用Response.BinaryWrite()之后。

    在response.binarywrite之后,您可能无意中发送了其他内容,这可能会混淆浏览器。end将确保浏览器只得到您真正想要的。

        2
  •  16
  •   jinsungy    15 年前
            Response.BinaryWrite(bytes);
            Response.Flush();
            Response.Close();
            Response.End();
    

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

        3
  •  7
  •   Robin Day    15 年前

    我们已经成功地使用了它。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();
    
        4
  •  5
  •   LukeH    15 年前

    既然您直接从文件系统发送文件,而不进行中间处理,为什么不使用 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数据的页面内容的其余部分。)

        5
  •  4
  •   Nils    9 年前

    仅供将来参考,如本文所述: http://blogs.msdn.com/b/aspnetue/archive/2010/05/25/response-end-response-close-and-how-customer-feedback-helps-us-improve-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();
    
        6
  •  2
  •   Faisal    13 年前
        7
  •  1
  •   Igor Zelaya    15 年前

    可能缺少响应。关闭de binary流

        8
  •  1
  •   Mr Zachary    6 年前

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

    //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=新blob([response.data],类型:类型];” 如果您不首先解压缩,那么当您将字节数组转换为JavaScript中的文件时,这将给您提供一个试图打开的无效/损坏的文件。

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

        9
  •  0
  •   AJ.    15 年前

    除了igor的response.close()之外,我还将添加response.flush()。

        10
  •  0
  •   extremeandy    9 年前

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

    Response.Encoding = Encoding.Default
    

    如果我不包括这个,我的jpeg就损坏了,以字节为单位的大小增加了一倍。

    但仅当处理程序从ASPX页返回时。它似乎是从一个阿什克斯运行这是不需要的。