descargar un archivo que viene como archivo adjunto en una respuesta de solicitud POST en PhantomJs

Quiero descargar un archivo CSV, se genera con un clic de botón a través de una solicitud POST. Investigué lo mejor posible en los foros de casperJs y phantomJS y regresé con las manos vacías. En un navegador normal como Firefox, aparece una ventana de diálogo de descarga del navegador después de la solicitud. Cómo manejar este caso en 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 

He encontrado una manera de hacer esto usando casperjs (debería funcionar solo con phantomjs si implementa la función de descarga usando XMLHttpRequest, pero no lo he intentado).

Te dejo el ejemplo de trabajo, que intenta descargar el último archivo PDF de esta página . Cuando hace clic en el enlace de descarga, se activa un código de JavaScript que genera algunos campos de entrada ocultos que luego se POST.

Lo que hacemos es reemplazar la función onsubmit del formulario para que cancele el envío y obtenga el destino del formulario (acción) y todos sus campos. Usamos esta información más tarde para hacer la descarga real.

 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(); 

Nota: debe ejecutarlo con --ignore-ssl-errors, ya que la CA que utiliza no se encuentra en la lista CA predeterminada de su navegador.

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

Puede escuchar el evento page.resource.received y download() el archivo cuando lo reciba:

 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 es casi la solución, pero en mi caso no tenía el nombre correcto para reemplazar el envío del formulario.

Entonces encontré otra solución usando phantomjs beta:

Hay una versión beta de phantomjs 2.0 que incluye un controlador de eventos que resuelve este problema.

Todavía es una versión beta, por lo que no hay depuración.

Así que desarrollé los clics y los tratamientos de página en la versión de lanzamiento y luego cambié la versión fantasma para que funcione la descarga.

  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(); 

Descargar: Phantom 2.0 BETA

Descargue el exe, cambie el nombre de la versión de lanzamiento de phantom.exe a phantom.bkp.exe e inserte esta versión 2.0 en el lugar. Luego, en casperjs necesitarás agregar algunas líneas al principio de 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; 

también comente la verificación de versión (mismo archivo):

 (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); 

Recuerde, esto es un ajuste !!

Así que estas líneas en bootstrap causarán problemas si quieres ejecutar la versión de lanzamiento fantasma o slimerjs.

Así que DESARROLLAR EN LA VERSIÓN DE LIBERACIÓN, que ajustar a esta versión para poder descargar. Si necesita depurar, deberá eliminar las líneas de bootstrap.js

Tengo que lidiar con un sitio escrito con algún tipo de marco ASP.Net que envía una cantidad notable de datos POST en cada solicitud (unos 100 Kb de datos, de los cuales alrededor de 95 nunca parecen cambiar entre las solicitudes, aparentemente relacionadas con el estado de las ventanas) .

Sin embargo, ningún método que pude encontrar funcionó para mí. He intentado interceptar XHR , incluso he encontrado a alguien que está abordando el mismo marco (al menos a juzgar por los selectores) pero con un caso más simple, inspirado en esta misma pregunta. Descubrí que en el pasado esto no se podía hacer con PhantomJS.

Mi problema es que al hacer clic en un botón se inicia una cadena de solicitudes AJAX que culmina con el envío de este enorme formulario POST, al que finalmente el servidor responde con una “Disposición de contenido: archivo adjunto”.

Al final, encontré este enfoque que funciona para mí, incluso si es ineficiente en la red:

 ...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); 

La descarga funciona sin problemas, incluso si puedo ver que el archivo se solicita (y envía) dos veces .

 [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" 

(A continuación, probablemente modifique el script para intentar invocar request.abort() desde el resource.requested listener solicitado, establezca un semáforo e invoque de nuevo el progtwig de descarga; no podré obtener el nombre del archivo adjunto, pero eso importa poco para mí).

    Intereting Posts