如何在CasperJS中下载多个PDF文件

如何在CasperJS中下载多个PDF文件,pdf,phantomjs,casperjs,Pdf,Phantomjs,Casperjs,我想使用CasperJS从站点下载.pdf文件列表。它基本上是有效的,但最后几个PDF文件被截断了。以下是相关的代码片段: casper.then(function a09() { for (var index = bill_count-1; index>=0; --index) { casper.then(downloadOnePdf(index)); }; }); function downloadOnePdf(index) { return

我想使用CasperJS从站点下载.pdf文件列表。它基本上是有效的,但最后几个PDF文件被截断了。以下是相关的代码片段:

casper.then(function a09() {
    for (var index = bill_count-1; index>=0; --index) {
        casper.then(downloadOnePdf(index));
    };
});

function downloadOnePdf(index) {
    return function() {
        var selector = 'div#myAjaxDiv tbody tr:nth-child(' + (index+1) + ') form a'
        casper.log('click ' + selector, 'info');
        casper.click(selector);
        // casper.waitForResource(/\/Document/); -- see note
        // casper.waitForText('%%EOF'); -- see note
    };
};

casper.run();
通过web代理观看此代码的执行,我可以看到.pdf文件作为响应主体到达。但是,最后两三个文件没有完全下载-它们被截断了-我在响应头中看到一条消息“客户端在接收整个响应之前关闭连接”

这支持了我的直觉,即casperjs代码在pdf完全下载之前就已经存在了。我试着添加一个

casper.waitForResource(/\/Document/)
在我的代码中,但这没有帮助。我还尝试:

casper.waitForText('%%EOF')
但是,即使我可以在响应正文中看到“%%EOF”,该操作也超时了

所以问题是:什么是确保整个.pdf文件到达响应体的正确方法


注:细心的读者会注意到我实际上并没有保存.pdf数据。这是另一天的问题…

原来,原始帖子中被截断的文件只是更大问题的一小部分,但解决方案并没有那么困难。让我解释一下

CasperJS不提供对响应主体的直接访问,因此OP的casper.click方法无法访问返回响应中PDF数据的表单。抱歉,没有办法将数据保存到本地文件系统上

相反,您需要调用casper.download发布与单击表单时相同的表单。这种方法的关键点很简单,尽管文档很少:

以任何适当的方式加载包含表的DOM 对于这种情况。 使用CSS的第n个子伪类从表中选择单个行。 使用casper.getFormValues构建可邮寄表单。 使用casper.download发布表单并保存结果数据。 下面是相关的代码摘录。我希望有人会觉得这很有用,即使几个月后那个人就是我:

// ========== helpers
// The following helpers assume that the current DOM contains the table with the download forms

// Return the number of PDFs available for download.  
function countPDFs() {
    return casper.getElementsAttribute('div#myAjaxDiv tbody tr form input[name="id"]', 'value').length
}

// Get the invoice ID of the index'th invoice: 0 <= index < countPDFs().
function getInvoiceID(index) {
    return casper.getElementAttribute('div#myAjaxDiv tbody tr:nth-child(' + (index+1) + ') form input[name="id"]', 'value');
}

// Return the index'th form for downloading a .pdf: 0 <= index < countPDFs().
function getDownloadForm(index) {
    return casper.getFormValues('div#myAjaxDiv tbody tr:nth-child(' + (index+1) + ') form')
}

// Download the index'th PDF file, saving it to <target_directory>/<invoiceID>.pdf.  
// 0 <= index < countPDFs().
function downloadOnePDF(index, target_directory) {
    var 
      url = 'https://example.com/Invoice',
      target = target_directory + '/' + getInvoiceID(index) + '.pdf',
      data = getDownloadForm(index);

    casper.then(function d01() {
        casper.log('downloading pdf ' + index + ' to ' + url);
        casper.download(url, target, 'POST', data);
    });
}

// ========== casper agenda items

// (initial steps omitted)

// Click on "Invoice" button to bring up the Invoice page
var invoice_link_css = 'a#mnuInvoiceSubmit'
casper.then(function a06() {
    casper.click(invoice_link_css)
});

// Make sure the Invoice page has loaded, as evidenced by the presence of the
// bill history table.
casper.then(function a07() {
    casper.waitForSelector('div#myAjaxDiv tbody');
});

// Download each .pdf file referenced in the bill history table.
casper.then(function a08() {
    var pdf_count = countPDFs();

    casper.echo('found ' + pdf_count + ' past bill' + ((pdf_count == 1) ? '' : 's'));
    for (var index = pdf_count-1; index>=0; --index) {
        downloadOnePDF(index, target_directory);
    }
});

casper.run();

这种方法将每个.pdf文件保存到本地文件系统中,并且不会出现OP中的任何截断问题。

pdf文件是否很大,一个文件的下载持续多长时间?PhantomJS有一个任意的限制,下载时间不能超过30秒。也许也可以用SlimerJS试试。一个典型的pdf大约是150K,加载大约需要2秒钟。所以我们还远远没有达到30秒的极限。在收到整个响应消息之前,总是最后一个或两个文件关闭了客户端连接。您是否尝试过casper.wait?可能是一些异步问题。@Drops-no,但下载技术似乎可靠地避开了casper.wait的需要