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

Некоторые вопросы о написании потока ответов ASP.NET

Я делаю тесты с 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();
            }
        }
    }

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

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

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

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

4b9b3361

Ответ 1

  • Да; это нормально.
  • Если вы никогда не скрываете, браузер не получает никакого ответа до тех пор, пока не закончится serever (даже заголовок Content-Disposition). Поэтому он не знает, чтобы показать диалог с файлом.
  • Заголовок Content-Length устанавливается только в том случае, если весь отклик буферизирован (если вы никогда не скрываете), или если вы сами установили его. В этом случае вы можете и должны установить его самостоятельно; написать

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

Ответ 2

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

Ответ 3

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

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