загрузка файла, который поставляется в виде вложения в ответе запроса POST в PhantomJs

Я хочу загрузить CSV-файл, он создается при нажатии кнопки через запрос POST. Я исследовал все возможное на форумах casperJs и phantomJS и вернулся с пустыми armми. В обычном браузере, таком как firefox, после запроса на почту появляется диалоговое окно загрузки браузера. Как обрабатывать этот случай в 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 

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

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

Мы делаем замену функции 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, переименуйте версию версии phantom.exe в phantom.bkp.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); 

Помните, что это настройка!.

Таким образом, эти строки в бутстрапе вызовут проблемы, если вы хотите запустить фантомную версию выпуска или slimerjs.

Итак, РАЗРАБОТАТЬ ВЕРСИЯ RELEASE, а не настраивать эту версию, чтобы ее можно было загрузить. Если вам нужно отлаживать, вам придется удалить строки bootstrap.js

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

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

Моя проблема заключается в том, что нажатие кнопки запускает цепочку запросов AJAX, достигающую высшей точки с отправкой этой огромной формы POST, на которую, наконец, сервер отвечает «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 прослушивателя, установить семафор и снова вызвать загрузчика – я не смогу получить имя файла вложения, но это важно мало для меня).

Давайте будем гением компьютера.