当我使用普通浏览器(Chrome)浏览网站时,当我点击网站A上的链接时,Chrome会以CSV文件的形式下载报告。
当我检查服务器响应标头时,我得到以下结果:
Cache-Control:private,max-age=31536000
Connection:Keep-Alive
Content-Disposition:attachment; filename="report.csv"
Content-Encoding:gzip
Content-Language:de-DE
Content-Type:text/csv; charset=UTF-8
Date:Wed, 22 Jul 2015 12:44:30 GMT
Expires:Thu, 21 Jul 2016 12:44:30 GMT
Keep-Alive:timeout=15, max=75
Pragma:cache
Server:Apache
Transfer-Encoding:chunked
Vary:Accept-Encoding
现在,我想使用PhantomJS下载并解析此文件。我设置了page
onResourceReceived
监听器,看看Phantom是否会接收/下载该文件。
clientRequests.phantomPage.onResourceReceived = function(response) {
console.log('Response (#' + response.id + ', stage "' + response.stage + '"): ' + JSON.stringify(response));
};
当我发出Phantom请求下载文件时(这是page.open('文件的URL')),我可以在Phantom日志中看到该文件已下载。这是日志:
"contentType": "text/csv; charset=UTF-8",
"headers": {
"name": "Date",
"value": "Wed, 22 Jul 2015 12:57:41 GMT"
},
"name": "Content-Disposition",
"value": "attachment; filename=\"report.csv\"",
"status":200,"statusText":"OK"
我收到了文件及其内容,但是如何访问文件数据?当我打印当前的PhantomJS page
对象时,我得到了页面A的HTML而我不想要它,我想要CSV文件,我需要使用JavaScript解析它。
答案 0 :(得分:12)
我找到了PhantomJS的解决方案。阅读discussion我发现jsfiddle通过jQuery的ajax方法下载了一个url,并将该文件编码为base64。
我想下载的文件是纯文本(CSV),所以我删除了编码功能。我的目标页面也已包含jQuery,因此我不需要inject jQuery into the target page。
我的代码假设您已经使用PhantomJS打开了要下载文件的页面,并且该页面中包含jQuery。在我的情况下,我必须首先登录该网站才能获得下载链接。
var fs = require('fs');
var page=this;
var result = page.evaluate(function() {
var out;
$.ajax({
'async' : false,
'url' : 'fullurltodownload.csv',
'success' : function(data, status, xhr) {
out = data;
}
});
return out;
});
fs.write('mydownloadedfile.csv', result);
答案 1 :(得分:8)
经过几天的调查后,我不得不说有一些解决方案:
如果您需要使用PhanotmJS下载文件,然后离开PhantomJS并使用CasperJS 。 CasperJS基于PhantomJS,但它具有更好,更直观的语法和程序流程。
以下是解释“Why CasperJS is better than PhantomJS”的好帖子。在这篇文章中,您可以找到有关文件下载的部分。
如何使用CasperJS下载CSV文件(即使在服务器发送标题Content-Disposition:attachment; filename='file.csv
时也可以这样做)
在这里,您可以找到一些可供下载的自定义csv文件:http://captaincoffee.com.au/dump/items.csv
要使用CasperJS下载此文件,请执行以下代码:
var casper = require('casper').create();
casper.start("http://captaincoffee.com.au/dump/", function() {
this.echo(this.getTitle())
});
casper.then(function(){
var url = 'http://captaincoffee.com.au/dump/csv.csv';
require('utils').dump(this.base64encode(url, 'get'));
});
casper.run();
上面的代码将下载http://captaincoffee.com.au/dump/csv.csv
CSV文件,并将结果打印为base64字符串。所以这样,您甚至不必将数据下载到文件中,您将数据作为base64字符串。
如果您明确要将文件下载到文件系统,则可以使用CasperJS中提供的download
函数。
答案 2 :(得分:1)
前2个答案假设您可以提前知道最终CSV文件的URL。如果链接转到HTML页面,该页面执行Javascript计算重定向到文件,并且您不想在PhantomJS之外评估该Javascript,则情况不会如此。您的选择是:
text/plain
并删除Content-Disposition
标题,这样您就可以正常方式从PhantomJS中读取文件 - 这应该适用于CSV文件但是对于其中包含0字节的二进制文件不起作用。如果上游代理可以监控PhantomJS发送到远程站点的Accept
标头,则第一个选项(PhantomJS +上游代理)变得更容易。至少在PhantomJS版本2.1.1中,主要请求有Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
,样式表请求有Accept: text/css,*/*;q=0.1
,所有其他请求(图像,脚本,XMLHttpRequest)默认为Accept: */*
,尽管这可以被覆盖使用XMLHttpRequest.setRequestHeader()
的网站。因此,如果上游代理看到带有Accept
标头的请求包含text/html
,并且将此请求传递给服务器,则会生成CSV文件或其他非HTML文档,那么这是一个很好的机会,这是一个可以拯救的人。