Как не прервать 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
Я до сих пор не нашел хорошего решения. Я хотел бы выполнить некоторые действия после того, как пользователь загрузил файл, но без использования отдельной страницы для ответа / запроса.

 Daniel A. White28 мая 2012 г., 03:14
http не работает так. его 1 запрос приводит к 1 ответу.
 Peter06 июн. 2012 г., 16:20
какие-либо вопросы по моему ответу до того, как закончится щедрость?
 Ray Cheng28 мая 2012 г., 04:14
при условии, что ваш код на стороне сервера запускается через клик / постбэк клиента. Вы можете запустить два запроса от клиента. Таким образом, вы можете поместить всю свою логику на одной странице.
 user19407628 мая 2012 г., 05:19
@RayCheng, но мне нужно, чтобы мой второй ответ был запущен после завершения первого ответа без взаимодействия с пользователем.

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

Don't use response.End();

Declare this global var : bool isFileDownLoad;

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

Override your Render like :

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

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

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

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

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

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

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 в целом). или жеНаправление на новую страницу после загрузки файла.

 01 июн. 2012 г., 20:22
@ user194076 - Я обновил свой ответ, чтобы включить вариант с одной страницей, который может работать для вас. Хотя, честно говоря, это в основном способ подделать опцию дополнительной страницы ...
 user19407606 июн. 2012 г., 19:10
Круто, спасибо. Я постараюсь поиграть с ним в ближайшие несколько часов и отправить ответ, если у меня возникнут дополнительные вопросы.
 06 июн. 2012 г., 19:04
@ user194076 - Я добавил ссылку на то, что выглядит как отличный пример. Он даже использует панель обновления и iframe, как вы и просили.
 user19407601 июн. 2012 г., 20:04
Если я не вызываю response.end, то сгенерированный файл поврежден. может быть, есть еще одна проблема, но все же: если я делаю что-то вроде response.Flush (); button.Visible = ложь; он не скрывает кнопку. Или grid.DataBind () также не работает.
 user19407606 июн. 2012 г., 18:22
Я еще не пытался реализовать это, но был бы полезен простой пример того, как добиться поведения с помощью iframe и панели обновления.

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 не общаются друг с другом, если вы не внедрилиэтот.

возвращение файла 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.

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

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 для вашего перенаправленного постраничного.

 28 мая 2012 г., 07:44
если ваш pdf сгенерирован с помощью ashx, вы можете выполнить обработку базы данных, прежде чем завершить ответ там.
 user19407628 мая 2012 г., 07:35
Спасибо за ответ. Я знаю, что response.end () вызывает исключение. Я не могу использовать таймер для перенаправления на другую страницу, так как я не знаю длительности обработки. Кроме того, в другом месте мне нужно выполнить запрос к базе данных после того, как пользователь скачал файл. Я не могу сделать это с помощью JavaScript.
 28 мая 2012 г., 07:46
Сценарий таймера может быть добавлен в ответ, который вы отправляете после создания PDF. Этот сценарий сам установит location.pref в ваш путь ashx, чтобы скачать pdf.

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

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

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

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