Вопрос по extjs, download, ajax, extjs4, http-post – Extjs 4 (с кодом для 3.4 ниже) загрузка файла, возвращенного из почтового запроса

4

Я видел вопросы, слегка связанные с этим, но ни один из них не отвечал моей проблеме. Я настроил Ext.Ajax.request следующим образом:

var paramsStringVar = 'param1=1&param2=two&param3=something&param4=etc';

Ext.Ajax.request({
  url: '/cgi-bin/url.pl',
  method:'POST',
  params:paramsStringVar,
  timeout:120000,
  success: function(response, opts){
    var objhtml = response.responseText; //content returned from server side
    console.log(objhtml);
  }

});

Этот запрос извлекает соответствующий контент из серверной части. Одним из параметров является outputType, который может принимать значения {html, excel, csv}. При возврате HTML для отображения я могу обрабатывать и отображать его правильно. Теперь к проблеме ...

Когда я устанавливаю для параметра outputType значение csv или excel, я возвращаю соответствующий контент в виде csv или tsv (excel) в соответствии с запросом. НО, мне не нужно содержимое, мне нужно приглашение загрузить файл (csv или excel). Как сделать так, чтобы браузер автоматически предлагал пользователю загрузить файл, а не просто извлекать текстовое содержимое в extjs?

Версия 4.07, поэтому я не могу использовать любые функции 4.1

Ваш Ответ

4   ответа
6

приглашение на загрузку / открытие на основе типа ответа text / csv. Обратите внимание, что никакой iFrame или ссылка на iframe не нужны. Я потратил много времени на одержимость iFrame, что фактически сломало мое решение. Для создания запроса на загрузку iFrame не требуется. Необходим запрос (submittal), аналогичный этому, вместе с бэкендом, генерирующим соответствующий csv с заголовком ответа text / csv.

var hiddenForm = Ext.create('Ext.form.Panel', {
  title:'hiddenForm',
  standardSubmit: true,
  url: /cgi-bin/url.pl
  timeout: 120000,
  height:0,
  width: 0,
  hidden:true,
  items:[
    {xtype:'hiddenField', name:'field1', value:'field1Value'},
    // additional fields
  ]
})

hiddenForm.getForm().submit()

Строка StandardSubmit жизненно важна

Цель: _blank не требуется в моем случае. Я упоминал в первом посте: «Когда я возвращаю html для отображения, я могу обработать и отобразить его правильно». Моя проблема была строго с запуском загрузки. Bbb
Я не могу присоединить слушателя к моему методу отправки, так как после выполнения этой процедуры мне нужно выполнить очистку, вам повезло?
Похоже, мы немного не поняли друг друга. Да, для запуска загрузки вам не нужен iframe. Но вы упомянули, что у вас также есть HTML-ответ, который вы хотите обработать и отобразить где-то в вашем интерфейсе, как я понял (When returning html to display I am able to handle and display it correctly.). Вам понадобится iframe для обработки незагруженного ответа. Но в любом случае, я предложил вам сначала попробовать код без iframe (с target _blank) перед тем, как "тратить время".
Я использую этот подход в успешном обратном вызове ajax-формы. Таким образом, если отправка формы ajax завершится успешно, я выполню standardSubmit, чтобы предложить ресурс, сохраненный в сеансе, для загрузки. В случае неудачной отправки ajax на панели появляется сообщение об ошибке.
0

        var hiddenForm = new Ext.FormPanel({
            id:'hiddenForm',
            region: 'south',
            method: 'POST',
            url: "/cgi/test.wsgi",
            height: 0,
            standardSubmit: true,
            hidden:true,
            items:[
                {xtype:'hidden', name:'p', value:p},
                {xtype:'hidden', name:'g', value:g},
                // ...
            ],
        });

        linkThis = new Ext.Button({
            text: 'Download this CSV',
            handler: function() {
                hiddenForm.getForm().submit();
            },
            maxHeight: 30,
        });

Помните, что для того, чтобы заставить его работать, вы должны поместить hiddenForm в любой контейнер (то есть в то же Ext.Window кнопки), например:

  risultatiWindow = new Ext.Window({
            title: 'CSV Export',
            height: 400,
            width: 500,
            ....
            items: [...., hiddenForm]
 });
0

Мы можем добавить html-форму и по нажатию кнопки в файле extjs мы можем отправить форму, используя URL-адрес. Это будет работать как в IE, так и в браузерах Chrome. Ниже мой код, который я пробовал, и он работает нормально,

<form action="<%=fullURL%>/DownloadServlet.do" method="get" id="downloadForm"   name="downloadForm" target="_self">
</form>

click: 
  {
     fn: function()
    { 
       document.getElementById('downloadForm').submit();    
    }
  }   
7

нет пуленепробиваемого решения, но я бы попробовал несколько подходов:

1) Используйтеiframe вместо реального XHR для отправки данных на сервер, например<form action="/something" target="myiframe"> гдеmyiframe этоname вашего скрытого фрейма. Таким образом, ваша форма будет использовать iframe (а не главное окно) для отправки данных на настроенный URL. Ваш сервер должен установить заголовок ответа какapplication/octet-stream (или какой-то другой MIME-тип для двоичных данных), поэтому браузер запускает загрузку. В противном случае (если html возвращается в вашем случае) вы можете просто получить тело iframe innerHTML и отобразить его пользователю в пользовательском интерфейсе. Хотя использование iframe (или нового окна) вместо XHR не кажется лучшей идеей, это решение кажется наиболее надежным (и с лучшей поддержкой браузера).

Вот немного измененный пример изExt.form.Basic страница документов:

Ext.create('Ext.form.Panel', {
    title: 'Basic Form',
    renderTo: Ext.getBody(),
    width: 350,

    // Any configuration items here will be automatically passed along to
    // the Ext.form.Basic instance when it gets created.

    // *THIS* makes the form use a standard submit mechanism, not XHR
/**/standardSubmit: true,

    // URL to submit to
    url: 'save-form.php',

    items: [{
        fieldLabel: 'Field',
        xtype: 'textfield',
        name: 'theField'
    }],

    buttons: [{
        text: 'Submit',
        handler: function() {
            // The getForm() method returns the Ext.form.Basic instance:
            var form = this.up('form').getForm();
            if (form.isValid()) {
                // Submit the Ajax request and handle the response
                form.submit({
                    success: function(form, action) {
                       Ext.Msg.alert('Success', action.result.msg);
                    },
                    failure: function(form, action) {
                        Ext.Msg.alert('Failed', action.result.msg);
                    },

                    // You can put the name of your iframe here instead of _blank
                    // this parameter makes its way to Ext.form.Basic.doAction() 
                    // and further leads to creation of StandardSubmit action instance
/**/                target: '_blank'                        
                });
            }
        }
    }]
});

Здесь есть два ключевых параметра (строки помечены/**/):

standardSubmit: true config that you pass to your form will make it do a standard submit instead of XHR. Passing a target parameter to the form's submit action. This feature is not documented but you can see it being used in Ext.form.action.Submit source code (all options that you pass to Ext.form.Basic.submit() method end up as parameters of Ext.form.action.* instance.

В примере кода я положилtarget: '_blank' продемонстрировать, что он работает сразу (создаст новое окно браузера). Вы можете заменить его именем своего iframe позже, но я предлагаю сначала проверить, как ваша форма отправляет данные в обычное новое окно, а затем разработать логику, которая создает и обрабатывает iframe. Вам придется обрабатывать результат внутри iframe самостоятельно, подумал. Это не так сложно, понимаетеExt.data.Connection.upload () реализация в качестве примера обработки iframe.

ExtJS на самом деле уже используетiframe техника для файлаuploads, УвидетьExt.data.Connection а такжеExt.form.field.Field.isFileUpload () для идеи о том, как это может работать.

2) Предложено здесь:Использование HTML5 / Javascript для генерации и сохранения файла.

Если вы не хотите идти по пути iframe, попробуйте создатьdata URI из данных ответа и перейдите к этому URI, инициирующему загрузку:

content = "Hello world!";
uriContent = "data:application/octet-stream," + encodeURIComponent(content);
window.location.href = uriContent;

Опять же, Mimetype имеет важное значение здесь. Это сработало для меня, однако вы должны заметить, что браузеры накладывают ограничение на размер URI данных (256Кб - безопасная ставка).

3) Еще один ответ в упомянутой теме ссылки наFileSaver.js библиотека реализует (заброшенный?) спецификацию w3. Использование и демоВот, Он использует [BlobBuilder] для генерации двоичного объекта двоичных данных, который затем используется для инициализации загрузок с использованием одного из нескольких методов. Хотя это решение, похоже, работает, оно использует устаревшие API и не может быть ориентировано на будущее.

Хочу ли я вставлять HTML для скрытых полей формы в Iframe? Если да, то как в extjs установить значения полей, а затем опубликовать форму? Bbb
Не могли бы вы предоставить пример кода? Я не делал этого раньше, и я должен был пропустить шаг. Я публикую в Iframe, но как? Bbb
Я обновил пункт 1) в своем ответе. Вы не помещаете свои поля в iframe, вы оставляете их там, где они сейчас находятся в вашем приложении, вы просто настраиваете свою форму для отправки данных в iframe с использованием обычного синхронного запроса, а не XHR. УвидетьExt.form.Basic.standardSubmit.
Как отличить XHR от обычного синхронного запроса? В отличие от Ext.Ajax.Request, что бы я использовал, чтобы сделать запрос? Bbb
Когда вы говорите: «Используйте iframe». Вы имеете в виду вставить iframe (скрытый) в мою панель и что дальше? Bbb

Похожие вопросы