после использования Page.Response для отправки файла пользователю страница не отвечает - PullRequest
1 голос
/ 03 февраля 2010

Я создал страницу, которая позволяет пользователям загружать файл при нажатии кнопки ... Событие onclick кнопки связано со следующим фрагментом кода:

this.Page.Response.Clear();
this.Page.Response.ContentType = System.Net.Mime.MediaTypeNames.Application.Zip;
this.Page.Response.AppendHeader("Content-Disposition", "attachment; filename=\"" + System.IO.Path.GetFileName(filename) + "\"");
this.Page.Response.TransmitFile(filename);
this.Page.Response.Flush();
this.Page.Response.End();

Загрузка работает нормально, но теперь, когда я пытаюсь взаимодействовать со страницей (например, снова нажать кнопку загрузки), ничего не отправляется обратно.

Я неправильно отвечаю на запрос на загрузку (должен ли я использовать другой / новый объект ответа), или мне нужно что-то еще сделать, чтобы страница стала активной после загрузки?


Edit:

Итак, я попытался объединить два предложения для создания httphandler и вызвать Response.Redirect для обработчика из события нажатия кнопки.

    void submitButton_Click(object sender, EventArgs e)
    {
        label.Text = "Boo!";
        this.Page.Response.Redirect("~/ViewAttachment.ashx?id=foo", false);
    }

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

Ответы [ 3 ]

3 голосов
/ 03 февраля 2010

Если используется другой обработчик, опция?

Вот уменьшенная версия того, что я использовал раньше (предложения приветствуют, это была быстрая запись). HttpHandler (AttachmentFile - это просто класс с данными BLOB-объектов и некоторыми атрибутами, собранными при загрузке файла):

public class AttachmentHandler : IHttpHandler
{
  public const string QueryKeyID = "ID";

  public void ProcessRequest(HttpContext context)
  {    
    var r = context.Response;
    var attachmentID = context.Request.QueryString[QueryKeyID];

    Attachment a = DataContext.GetById<AttachmentFile>(attachmentID);

    r.ContentType = a.ContentType;
    r.AppendHeader("Content-Type", a.ContentType);
    r.AppendHeader("content-disposition", string.Format("attachment; filename=\"{0}{1}\"", a.AttachmentName, GetExtension(a.FileName)));
    r.BufferOutput = false; //Stream the content to the client, no need to cache entire streams in memory...
    r.BinaryWrite(a.BlobData);
    r.End();
  }

  private static string GetExtension(string fileName)
  {
    if(fileName.IsNullOrEmpty()) return string.Empty;
    var i = fileName.LastIndexOf(".");
    return i > 0 ? fileName.Substring(i) : string.Empty;
  }
}

В web.config:

<system.web>
  <httpHandlers>
    <add verb="*" path="ViewAttachment.ashx" type="MyNamespace.AttachmentHandler, MyWebDllName"/>
  </httpHandlers>
</system.web>

Тогда все, что вам нужно сделать - это отобразить на странице ссылку в виде ~/ViewAttachment.ashx?ID=5, нажав кнопку, чтобы загрузить файл, но не нарушить жизненный цикл вашей страницы.

Теперь есть и другие соображения, такие как безопасность и т. Д. Я обрезал их для этого примера. Я также использую этот стиль ссылок: ~/Attachment/{id} через маршрутизацию веб-форм ... если вас интересует какой-либо из этих вариантов, я обновлю их, чтобы включить. Или вы могли бы ненавидеть этот подход все вместе ... просто давая вам знать, что это вариант.

1 голос
/ 03 февраля 2010

Вы в основном там.

Все, что вам нужно сделать в обработчике событий нажатия кнопки - это Response.Radirect на другую страницу ASPX. Поместите этот код, который вы написали на другой странице.

Тогда все будет работать так, как вы ожидаете. Браузер фактически останется на исходной странице и не перейдет на новую страницу, потому что вы установили расположение содержимого в качестве вложения - и это прекрасно.

0 голосов
/ 03 февраля 2010

Используя Response.Clear (), вы убили заголовки. Хотя в браузере может отображаться верная HTML-разметка, на самом деле ее нет. Заголовки исчезли, поэтому элементы управления, которые по-прежнему отображаются, недействительны. Если вы нажмете «назад», вы сможете разместить информацию. Что вы, вероятно, хотите сделать, это сделать этот вызов в другом окне, используя PostBackUrl при нажатии кнопки и установив цель вашей формы в другое окно (затем используя SetTimeout, чтобы сбросить его на _self).

...