Подтвердить что ты не робот

Чтение двоичного файла и использование Response.BinaryWrite()

У меня есть приложение, которое должно читать 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);
}
4b9b3361

Ответ 1

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

Response.End();

после вызова функции Response.BinaryWrite().

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

Ответ 2

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

Это работает для нас. Мы создаем PDF файлы из SQL Reporting Services.

Ответ 3

Мы использовали это с большим успехом. 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

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

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

Ответ 7

Возможно, вам не хватает Response.close для закрытия двоичного потока

Ответ 8

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

Ответ 9

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

Response.Encoding = Encoding.Default

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

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

Ответ 10

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