Чтение двоичного файла и использование Response.BinaryWrite () - PullRequest
21 голосов
/ 11 мая 2009

У меня есть приложение, которое должно прочитать файл PDF из файловой системы, а затем записать его пользователю. PDF 183 КБ и, кажется, работает отлично. Когда я использую код внизу, браузер получает файл размером 224 КБ, и я получаю сообщение от 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 ]

24 голосов
/ 11 мая 2009

Попробуйте добавить

Response.End ();

после вызова Response.BinaryWrite ().

Возможно, вы случайно отправили другой контент после Response.BinaryWrite, что может запутать браузер. Response.End гарантирует, что браузер получит только то, что вы действительно хотите.

16 голосов
/ 11 мая 2009
        Response.BinaryWrite(bytes);
        Response.Flush();
        Response.Close();
        Response.End();

Это работает для нас. Мы создаем PDF-файлы из служб отчетов SQL.

7 голосов
/ 11 мая 2009

Мы использовали это с большим успехом. 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();
5 голосов
/ 11 мая 2009

Поскольку вы отправляете файл напрямую из вашей файловой системы без промежуточной обработки, почему бы не использовать вместо него 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.)

4 голосов
/ 17 июня 2015

Только для дальнейшего использования, как указано в этом сообщении в блоге: 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();
2 голосов
/ 14 марта 2011

Пожалуйста, прочтите это перед использованием Response.TransmitFile: http://improve.dk/blog/2008/03/29/response-transmitfile-close-will-kill-your-application

1 голос
/ 15 декабря 2017

В моем приложении MVC я включил сжатие gzip для всех ответов. Если вы читаете эту двоичную запись из ajax-вызова с gzipped ответами, вы получаете 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('<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});" Это даст вам тот неверный / поврежденный файл, который вы пытаетесь открыть, когда вы превращаете этот байтовый массив в файл в своем javascript, если вы сначала не распакуете его.

Чтобы исправить это, у вас есть выбор: либо запретить сжатие этих двоичных данных, чтобы вы могли правильно превратить их в загружаемый файл, либо вам нужно распаковать эти сжатые данные в коде JavaScript перед тем, как превратить их в файл.

1 голос
/ 11 мая 2009

Возможно, вам не хватает Response.close, чтобы закрыть de Binary Stream

0 голосов
/ 28 октября 2014

Я также счел необходимым добавить следующее:

Response.Encoding = Encoding.Default

Если я не включил это, мой JPEG был поврежден и удвоил размер в байтах.

Но только если обработчик возвращался со страницы ASPX. Казалось, работает с ASHX это не требуется.

0 голосов
/ 11 мая 2009

В дополнение к Response.Close (Igor) я бы добавил Response.Flush ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...