Кнопка включения после записи файла в ответ

#c# #asp.net

#c# #asp.net

Вопрос:

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

У меня следующая ситуация:

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

  GenerateBTN.Attributes.Add("onclick", "this.disabled=true;"   ClientScript.GetPostBackEventReference(GenerateBTN, "").ToString());
  

После обработки событий Page_Load обработчик GenerateBTN_Click выполняет код, необходимый для генерации файла, и в конце этого метода (обработчика) Я пишу ответ, сгенерированный файл со следующим кодом:

 Response.Clear();
Response.ContentType = "application/octet-stream";                
Response.AddHeader("Content-Disposition", "attachment; filename=""   filename   """);
Response.WriteFile(@"C:Reports"   filename);
Response.End();    
  

Появляется диалоговое окно Сохранить как, и пользователь может загрузить сгенерированный файл, но проблема в том, что отключенный GenerateBTN остается отключенным. Как включить ее после записи сгенерированного файла в ответ? Я понимаю, что после очистки текущего ответа я не могу продолжить с первоначальным ответом, но есть ли какой-либо способ решить эту проблему?

Комментарии:

1. Включение кнопки с задержкой в несколько секунд в javascript может быть приемлемым взломом здесь. Обратите внимание, что 2 фрагмента кода в questoin выполняются в разных экземплярах страницы; второй ответ даже не является HTML и никак не может повлиять на исходную страницу. По-прежнему возможно заставить их взаимодействовать, но для этого потребуются дополнительные элементы и больше кода, например, вы можете повторно включить эту кнопку через AJAX.

Ответ №1:

Вы можете поместить IFrame на страницу и установить для его видимости значение hidden. Пусть ваша кнопка загрузит файл в IFrame и использует Javascript, чтобы определить, загружается ли IFrame все еще или нет. Когда загрузка будет завершена, включите вашу кнопку.

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

Редактировать для 2-го ответа

Что вы хотите сделать, это создать файл типа «Download.aspx», который вы передаете в имени файла в качестве параметра querystring. Таким образом, вы можете заставить свой сервер получить файл из местоположения за пределами пути веб-приложения и настроить заголовок для принудительной загрузки файла.

Загрузить.aspx

   using System.IO;
  
     protected void Page_Load(object sender, EventArgs e)
    {
        string FileName = Server.UrlDecode(Request.Params["FileName"]);  //Example: "MyFile.txt"

        Response.AppendHeader("Content-Type", "application/force-download");
        Response.AppendHeader("Content-Disposition", "attachment; filename="   FileName);
        Response.WriteFile(@"C:MyFolder"   FileName);
    }
  

Вы бы загрузили страницу, вызвав что-то вроде «Download.aspx?FileName=MyFile.txt «

Вам нужно будет добавить проверки, чтобы убедиться, что файл существует и параметр querystring существует, но это должно принудительно загрузить и позволить вам получить файл из другого местоположения. Когда вы используете ASPX-страницу для обслуживания файла, вы также можете выполнить проверку учетных данных, чтобы увидеть, зарегистрирован ли пользователь на вашем сайте (если у вас уже есть логика входа) или зарегистрировать загрузку в файле журнала / базе данных, если вы хотите отслеживать это. Это дает вам намного больше контроля над процессом загрузки.

Что касается кода загрузки IFrame, я не уверен на 100%, как это работает при загрузке файла, но то, что я изначально думал, было чем-то вроде этого — посмотреть источник на:http://sykari.net/stuff/iframe .

Комментарии:

1. Можете ли вы взглянуть на мой последний ответ? Я не вставил это в комментарий из-за ограничения символов…

Ответ №2:

Перенесите кнопку в панель обновления, затем просто переключите ее свойство enabled до и после работы с файлом.

Комментарии:

1. Я почти уверен, что вы не можете одновременно выводить файл и HTML (etc) в браузер в одном ответе. Я думаю, ему все еще нужно отправить файл или javascript, используя отдельный фрейм…

Ответ №3:

Вы можете поместить IFrame на страницу и установить для его видимости значение hidden. Пусть ваша кнопка загрузит файл в IFrame и использует Javascript, чтобы определить, загружается ли IFrame все еще или нет. Когда загрузка будет завершена, включите вашу кнопку.

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

Я решил воспользоваться вашим предложением.. но у меня все еще есть некоторые вопросы относительно этой проблемы…
Возможно ли загружать файлы .txt в iframe? Возможно ли загрузить некоторые файлы, которые не включены в папку веб-приложения?

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

Для загрузки файлов в iframe я использовал следующий код:

 HiddenFrame.Attributes["src"] = /GeneratedFiles/   "test.zip";
  

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

Какой лучший обработчик событий javascript (jquery) (функция) для определения завершения загрузки Iframe? Я использовал функцию jquery:

  $("#ctl00_ContentPlaceHolder1_HiddenFrame").ready(function () {

        if ($("#ctl00_ContentPlaceHolder1_HiddenFrame").attr('src') != '') {

            $('#ctl00_ContentPlaceHolder1_GenerateSapFilesBTN').removeAttr("disabled");
        }
    });
  

Но похоже, что кнопка включается до того, как фактически появится диалоговое окно Сохранить как.. Возможно ли решить эту проблему с помощью этого типа EventHandler или я должен использовать какую-то другую функцию…