Некоторые вопросы о написании в потоке ответов ASP.NET - PullRequest
25 голосов
/ 03 апреля 2010

Я делаю тесты с ASP.NET HttpHandler для загрузки файла записи непосредственно в поток ответов, и я не совсем уверен в том, как я это делаю. Это пример метода, в будущем файл может быть сохранен в BLOB в базе данных:

        public void GetFile(HttpResponse response)
    {
        String fileName = "example.iso";
        response.ClearHeaders();
        response.ClearContent();
        response.ContentType = "application/octet-stream";
        response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName);
        using (FileStream fs = new FileStream(Path.Combine(HttpContext.Current.Server.MapPath("~/App_Data"), fileName), FileMode.Open))
        {
            Byte[] buffer = new Byte[4096];
            Int32 readed = 0;

            while ((readed = fs.Read(buffer, 0, buffer.Length)) > 0)
            {
                response.OutputStream.Write(buffer, 0, readed);
                response.Flush();
            }
        }
    }

Но я не уверен, правильно ли это или есть лучший способ сделать это. Мои вопросы:

  1. Когда я открываю URL с помощью браузера, появляется диалоговое окно «Сохранить файл» ... но кажется, что сервер уже начал загружать данные в поток, прежде чем я нажимаю «Сохранить», это нормально?
  2. Если я удаляю строку «response.Flush ()», когда я открываю URL с помощью браузера, ... я вижу, как веб-сервер отправляет данные, но диалоговое окно «Сохранить файл» не появляется, (или, по крайней мере, не в разумных пределах) почему?
  3. Когда я открываю URL с помощью объекта WebRequest, я вижу, что HttpResponse.ContentLength равен «-1», хотя я могу прочитать поток и получить файл. В чем смысл -1? Когда HttpResponse.ContentLength будет показывать длину ответа? Например, у меня есть метод, который извлекает большой XML-файл, сжатый с deflate, в виде двоичного потока, но в этом случае ... когда я обращаюсь к нему с помощью WebRequest, в HttpResponse я на самом деле вижу ContentLength с длиной потока почему?
  4. Какова оптимальная длина массива Byte [], который я использую в качестве буфера для оптимальной производительности на веб-сервере? Я читал, что между 4K и 8K ... но какие факторы я должен учитывать, чтобы принять правильное решение.
  5. Раздражает ли этот метод использование памяти IIS или клиента? или это на самом деле буферизация переноса правильно?

Извините за столько вопросов, я довольно новичок в веб-разработке: P

Приветствие.

Ответы [ 3 ]

17 голосов
/ 03 апреля 2010
  1. Да; это нормально.
  2. Если вы никогда не выполните сброс, браузер не получит никакого ответа, пока сервер не завершит работу (даже заголовок Content-Disposition). Поэтому он не знает, чтобы показать файл диалога.
  3. Заголовок Content-Length устанавливается только в том случае, если весь ответ буферизирован (если вы никогда не очищаете) или если вы установили его самостоятельно. В этом случае вы можете и должны установить это самостоятельно; написать

    response.AppendHeader("Content-Length", new FileInfo(path).Length.ToString());
    
  4. Я рекомендую 4K; У меня нет твердой основы для рекомендации.
  5. Этот метод - лучший способ сделать это. Вызвав Flush внутри цикла, вы немедленно отправляете ответ по линии без какой-либо буферизации. Однако для повышения производительности вы можете использовать сжатие GZIP.
2 голосов
/ 03 апреля 2010

Для # 3 вам необходимо установить заголовок длины содержимого в вашем http-ответе. Многие из этих значений взяты из заголовков http.

Я полагаю, что вы можете изменить буферизацию, изменив свойство буферизации объекта ответа на false. Давно не делал этого, поэтому я не помню, что это может быть.

2 голосов
/ 03 апреля 2010
  1. Да, это буферизация.
  2. Flush передает кешированный контент в браузер. Если его не нажать, диалоговое окно сохранения не появится.
  3. Трудно сказать, не видя, какие именно файлы / URL / потоки вы используете.
  4. Я думаю, что факторы зависят от того, насколько медлительна ваша страница. Вы будете иметь лучшую производительность к 4k. И, возможно, более низкое значение будет лучше для размещения медленных соединений.
  5. См. № 1 и 2.
...