загрузив файл, который приходит как вложение в сообщение "запрос-ответ" с PhantomJS



Я хочу скачать CSV-файл, он генерируется по нажатию кнопки через POST-запрос. Я исследовал все, что мог, на форумах casperJs и phantomJS и вернулся с пустыми руками. В обычном браузере, например firefox, после запроса post появляется диалоговое окно загрузки браузера. Как справиться с этим случаем в PhantomJS



TTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
Content-disposition: attachment;filename=ExportData.csv
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Fri, 19 Apr 2013 23:26:40 GMT
Content-Length: 65183
445   4  

4 ответов:

Я нашел способ сделать это с помощью casperjs (он должен работать только с phantomjs, если вы реализуете функцию загрузки с помощью XMLHttpRequest, но я не пробовал).

Я оставлю вам рабочий пример, который пытается загрузить MOS recent PDF с этой страницы. При нажатии на ссылку загрузки запускается некоторый код javascript, который генерирует некоторые скрытые поля ввода, которые затем публикуются.

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

var casper=require('casper').create();
casper.start("https://sede.gobcan.es/tributos/jsf/publico/notificaciones/comparecencia/ultimosanuncios.jsp", function() {

    var theFormRequest = this.page.evaluate(function() {
        var request = {}; 
        var formDom = document.forms["resultadoUltimasNotif"];
        formDom.onsubmit = function() {
            //iterate the form fields
            var data = {};
            for(var i = 0; i < formDom.elements.length; i++) {
               data[formDom.elements[i].name] = formDom.elements[i].value;
            }
            request.action = formDom.action;
            request.data = data;
            return false; //Stop form submission
        }

        //Trigger the click on the link.
        var link = $("table.listado tbody tr:first a");
        link.click();

        return request; //Return the form data to casper
    });

    //Start the download
    casper.download(theFormRequest.action, "downloaded_file.pdf", "POST", theFormRequest.data);
});

casper.run(); 

Примечание: Вы должны запустить его с --ignore-ssl-errors, так как CA, который они используют, не находится в списке CA по умолчанию Вашего браузера.

casperjs --ignore-ssl-errors=true downloadscript.js

Вы можете прослушать событие page.resource.received и download() файл при получении:

casper.on('page.resource.received', function(resource) {
    if (resource.stage !== "end") {
        return;
    }
    if (resource.url.indexOf('ExportData.csv') > -1) {
        this.download(resource.url, 'ExportData.csv');
    }
});

@julianjm aproach-это почти решение, но в моем случае у меня не было правильного имени формы, чтобы заменить форму представления.

Поэтому я нашел другое решение, используя phantomjs beta:

Существует бета-версия phantomjs 2.0, которая включает обработчик событий, который решает эту проблему.

Это все еще бета-версия, так что нет никакой отладки.

Поэтому я разработал клики и обработку страниц в версии релиза, а затем изменил Фантом версия, чтобы скачать работу.

 casper.start('http://www.website.com.br/', function() {
    this.page.onFileDownload = function(status){console.log('onFileDownload(' + status + ')'); 

//SYSTEM WILL DETECT THE DOWNLOAD, BUT YOU WILL HAVE TO NAME THE FILE BY YOURSLEF!!
return "ContactList_08-25-14.csv"; };

    });
      casper.then(function() {
        //DO YOUR STUFF HERE TO CLICK ON THE DOWNLOAD LINK. 
      });
    casper.run();

Скачать: Phantom 2.0 BETA

Скачать exe, переименовать версии Фантома.ехе к фантому.БКП.exe и вставьте эту версию 2.0 на место. Затем в casperjs вам нужно будет добавить несколько строк в начале casperjs / bin / bootstrap.js

 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */
var system = require('system');
    var argsdeprecated = system.args;
    argsdeprecated.shift();
    phantom.args = argsdeprecated;

Также прокомментируйте проверку версии (тот же файл):

(function(version) {
        // required version check
      /*  if (version.major !== 1) {
            return __die('CasperJS needs PhantomJS v1.x');
        } if (version.minor < 8) {
            return __die('CasperJS needs at least PhantomJS v1.8 or later.');
        }
        if (version.minor === 8 && version.patch < 1) {
            return __die('CasperJS needs at least PhantomJS v1.8.1 or later.');
        } */
    })(phantom.version);

Помните, это хитрость!!.

Итак, это строки на bootstrap вызовут проблемы, если вы хотите запустить phantom release version или slimerjs.

Так что разрабатывайте на релизной версии, чем подстраиваться под эту версию, чтобы иметь возможность скачать. Если вам нужно выполнить отладку, вам придется удалить строки bootstrap.js

Мне приходится иметь дело с сайтом, написанным с какой-то ASP.Net фреймворк, который отправляет значительное количество данных POST при каждом запросе (около 100 Кб данных, из которых около 95 никогда не изменяются между запросами - состояние видового экрана, по-видимому, связано).

Однако ни один метод, который я мог найти, не работал на меня. Я изучил перехват XHR , я даже нашел кого-то, кто решает ту же самую структуру (по крайней мере, судя по селекторам), но с более простым случаем, вдохновленный этим самым вопросом. Я обнаружил, что в свое время это не могло быть сделано С PhantomJS.

Моя проблема заключается в том, что щелчок по кнопке запускает цепочку AJAX-запросов, кульминацией которых является отправка этой огромной почтовой формы, на которую сервер в конце концов отвечает "Content-Disposition: attachment".

В конце концов, я нашел этот подход, который работает для меня, даже если он неэффективен в сети:
...setting up everything, until I just need to click on a button...

phantomData    = null;
phantomRequest = null;

// Here, I just recognize the form being submitted and copy it.

casper.on('resource.requested', function(requestData, request) {
    for (var h in requestData.headers) {
        if (requestData.headers[h].name === 'Content-Type') {
            if (requestData.headers[h].value === 'application/x-www-form-urlencoded') {
                phantomData         = requestData;
                phantomRequest      = request;
            }
        }
    }
});

// Here, I recognize when the request has FAILED because PhantomJS does
// not support straight downloading.

casper.on('resource.received', function(resource) {
    for (var h in resource.headers) {
        if (resource.headers[h].name === 'content-disposition') {
            if (resource.stage === 'end') {
                if (phantomData) {
                    // to do: get name from resource.headers[h].value
                    casper.download(
                        resource.url,
                        "output.pdf",
                        phantomData.method,
                        phantomData.postData
                    );
                } else {
                    // Something went wrong.
                }
                // Possibly, remove listeners?
            }
        }
    }
});

// Now, click on the button and initiate the dance.
casper.click(pdfLinkSelector);

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

[debug] [phantom] Navigation requested: url=https://somesite/SomePage.aspx, type=FormSubmitted, willNavigate=true, isMainFrame=true
[debug] [application] GOT FORM, REQUEST DATA SAVED
[warning] [phantom] Loading resource failed with status=fail (HTTP 200): https://somesite/SomePage.aspx
[debug] [application] END STAGE REACHED, PHANTOMDATA PRESENT
[debug] [application] ATTEMPTING CASPERJS.DOWNLOAD
[debug] [remote] sendAJAX(): Using HTTP method: 'POST'
[debug] [phantom] Downloaded and saved resource in output.pdf
[debug] [application] TERMINATING SUCCESSFULLY
[debug] [phantom] Navigation requested: url=about:blank, type=Other, willNavigate=true, isMainFrame=true
[debug] [phantom] url changed to "about:blank"

(Далее я, вероятно, изменю сценарий, чтобы попытаться вызвать request.abort() из слушателя resource.requested, установить семафор и снова вызвать загрузчик - я не смогу получить имя файла вложения, но это мало что значит для меня).

Comments

    Ничего не найдено.