Как не прервать http ответ c #

Мне нужно запустить несколько методов после отправки файла пользователю для загрузки. Происходит следующее: после отправки файла пользователю ответ прерывается, и я больше не могу ничего делать послеresponse.end().

например, это мой пример кода:

 Response.Clear();
 Response.AddHeader("content-disposition", "attachment;  filename=test.pdf");
 Response.ContentType = "application/pdf";
 byte[] a = System.Text.Encoding.UTF8.GetBytes("test");
 Response.BinaryWrite(a);
 Response.End();
 StartNextMethod();
 Response.Redirect(URL);

Итак, в этом примереStartNextMethod а такжеResponse.Redirect не выполняются.

Я попытался создать отдельный обработчик (ashx) со следующим кодом:

public void ProcessRequest(HttpContext context)
        {
            context.Response.Clear();
            context.Response.AddHeader("content-disposition", "attachment;  filename=test.pdf");
            context.Response.ContentType = "application/pdf";
            byte[] a = System.Text.Encoding.UTF8.GetBytes("test");
            context.Response.BinaryWrite(a);
            context.Response.End();
        }

и назовите это так:

Download d = new Download();
d.ProcessRequest(HttpContext.Current);
StartNextMethod();
Response.Redirect(URL);

но такая же ошибка случается. Я попытался заменить Response.End на CompleteRequest, но это не помогло.

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

UPDATE
Я до сих пор не нашел хорошего решения. Я хотел бы выполнить некоторые действия после того, как пользователь загрузил файл, но без использования отдельной страницы для ответа / запроса.

Ответы на вопрос(8)

Загрузите файл кусками, как показаноЗагрузка файла в ASP.NET и отслеживание статуса успеха / сбоя загрузки или в ответ наэтот вопрос, Когда последний фрагмент файла был записан на клиент, вы можете выполнить необходимый код. (Не обязательно быть в конце, может быть где-то посередине в зависимости от ваших потребностей.)

Решение Вопроса

Update
Поскольку вы сказали, что нет второй страницы, сделайте это вместо этого. Добавьте раздел на свою страницу, который проверяет параметр строки запроса (что-то вроде fileid или path и т. Д.). Если это значение присутствует, оно инициирует процесс загрузки с использованием существующего кода. Если это значение отсутствует, то оно работает как обычно.

Теперь, когда пользователь нажимает на ссылку для скачивания, вы выполняете пост обратно (что вы уже делаете). В этом посте снова создайте iFrame на странице и установите URL-адрес iFrame для URL ваших страниц с добавленным параметром строки запроса (mypage.aspx? Id = 12664 или? Download = true, что-то в этом роде). После создания iframe выполните любые дополнительные привязки данных / etc ... вы тоже хотите.

Example
- http://encosia.com/ajax-file-downloads-and-iframes/

Этот выше связанный пример использует iFrame и панель обновления, как вы и говорили.

Original Post
Response.Flush позволит вам продолжить обработку после отправки файла пользователю или просто не вызывать Response.End (вам это действительно не нужно).

Однако Даниэль А. Уайт прав: вы не можете перенаправить код из своего кода после отправки файла, при попытке вы получите ошибку. НО вы можете продолжать выполнять другие операции на стороне сервера, если вам нужно.

Другие ответы согласуются с общим мнением, вы не можете перенаправить после начала загрузки файла:https://stackoverflow.com/a/822732/328968 (PHP, но те же понятия, поскольку он включает HTTP в целом). или жеНаправление на новую страницу после загрузки файла.

Я рекомендую это решение:

  1. Don't use response.End();

  2. Declare this global var : bool isFileDownLoad;

  3. Just after your (Response.BinaryWrite(a);) set ==> isFileDownLoad = true;

  4. Override your Render like :

    /// /// AEG : Very important to handle the thread aborted exception /// /// override protected void Render(HtmlTextWriter w) { if (!isFileDownLoad) base.Render(w); }

Я верю, что то, что вы пытаетесь, не сработает.

Вот что я бы сделал:

  1. Write content to a file locally and assign it an unique id
  2. send user to the next page that contains a hidden frame that perform a request with the unique id (javascript)
  3. hidden request page loads file and push on the content stream.

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

Недостаток: очистка файла.

Просто удалитеcontext.Response.End(); потому что вы все равно перенаправляете ...

Проблема здесь в некорректной логике .... Зачем тебе конец ответа?

Получить PDF и показать ссылку на него или использоватьMETA обновить, чтобы перенаправить на местоположение PDF или вы также можете отобразить ссылку или использовать комбинацию обоих методов.

Как говорилось в предыдущих ответах, возвращение файла PDF означает отправку заголовков HTTP. После этого вы не можете отправлять другие заголовки, а Response.Redirect () просто означает отправку HTTP 302.

Если вы не хотите иметь отдельную страницу, или если вы не хотите использовать AJAX, почему бы не попробовать:

<head>
    <meta http-equiv="refresh" content="3; url=http://www.site.com/download.aspx?xxxx">
</head>

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

пользователь нажимает на кнопку загрузки наWebForm1.aspx начать загрузку файла. затем, после завершения загрузки файла (обслуживаетсяWebForm2.aspx), пользователь автоматически перенаправляется.

WebForm1.aspx

<script type="text/javascript">
    $(document).ready(function () {
        $('#btnDL').click(function () {
            $('body').append('<iframe src="WebForm2.aspx" style="display:none;"></iframe>');
            return true;
        });
    });
</script>
<asp:Button runat="server" ID="btnDL" ClientIDMode="Static" Text="Download" OnClick="btnDL_Click" />

WebForm1.aspx.cs

protected void btnDL_Click(object sender, EventArgs e)
{
    var sent = Session["sent"];

    while (Session["sent"]==null)
    {// not sure if this is a bad idea or what but my cpu is NOT going nuts
    }

    StartNextMethod();
    Response.Redirect(URL);

}

WebForm2.aspx.cs

protected void Page_Load(object sender, EventArgs e)
{
    Response.Clear();
    Response.AddHeader("content-disposition", "attachment;  filename=test.pdf");
    Response.ContentType = "application/pdf";
    byte[] a = System.Text.Encoding.UTF8.GetBytes("test");
    Response.BinaryWrite(a);
    Session["sent"] = true;
}

Global.asax.cs

protected void Session_Start(object sender, EventArgs e)
{
    Session["init"] = 0; // init and allocate session data storage
}

Примечание. Убедитесь, что не используете ashx (универсальный обработчик) для загрузки. по какой-то причине сеансы в ashx и aspx не общаются друг с другом, если вы не внедрилиэтот.

Response.End () генерирует исключение прерывания потока. Он предназначен для завершения вашего ответа. Никакой код после этого не будет обрабатываться в этом потоке.

The End method causes the Web server to stop processing the script and return the current result. The remaining contents of the file are not processed.

Чего вы пытаетесь достичь?

Если ваша цель состоит в том, чтобы позволить PDF скачать и затем перевести пользователя на какую-то другую страницу, вам может помочь небольшой javascript.

Добавьте скрипт с таймером, чтобы установить location.href для вашего перенаправленного постраничного.

Ваш ответ на вопрос