2010-08-04 84 views
3

我有一个Perl脚本,它从远程服务器下载大量文件。我希望避免锤击服务器,所以如果自从上次检查后未修改文件,我想避免下载文件。有没有一种很好的方法来做到这一点,无论是在Perl或shell脚本?使用perl(或wget)下载新的/修改的文件

我可以让服务器发送HTTP 304而不是HTTP 200用于未修改的文件吗?

+0

rsync不是您可以实现的解决方案,而不是使用HTTP协议? – Wrikken 2010-08-04 20:11:04

+0

@Wrikken:不,它不是我的服务器! – Charles 2010-08-04 20:13:04

回答

5

是的,请使用LWP::UserAgent,并特别注意mirror方法。这在程序LWP::Simple中也可用作mirror函数。

LWP的POD:

该方法将得到由$ URL标识的文件并将其存储在文件名为$文件名。如果该文件已经存在,则该请求将包含与该文件的修改时间匹配的“If-Modified-Since”标头。如果服务器上的文档自此以后没有更改,则不会有任何反应。如果文档已更新,则会再次下载。该文件的修改时间将被迫与服务器的修改时间相匹配。

返回值是响应对象。

HTTP 304是服务器将返回的响应代码,如果您通过If-Modified-Since测试并且您的副本是新鲜的。 LWP通过mirror在内部完成 - 您无需担心。

+0

谢谢。有没有办法让它发送一个If-Modified-Since而没有真正的文件?我下载文件,检查它们是否正确,如果不是,则进行诊断。否则,我只是删除该文件并继续。 – Charles 2010-08-04 20:59:00

+2

是的。有。但是,使用LWP时,需要使用[HTTP :: Request](http://search.cpan.org/~gaas/libwww-perl-5.836/lib/HTTP/Request.pm)和'$ ua- > request()'直接。查看[LWP :: UserAgent]的源代码(http://cpansearch.perl.org/src/GAAS/libwww-perl-5.836/lib/LWP/UserAgent.pm)阅读mirror sub defn。如果你希望透明地发生这种情况,你也可以继承'LWP :: UserAgent'并覆盖镜像,子类化'LWP :: UserAgent'确实允许你做一些非常棒的事情。 – 2010-08-04 21:48:53

+1

我很高兴看到有什么东西存在。如果是这样,我已经准备好编写套接字接口了,但是看起来我不需要做更多的事情,而只需编写一些HTTP和一小段Perl。 感谢您的所有建议!我之前没有听说过LWP ......我想我需要花更多时间在CPAN上。 – Charles 2010-08-05 02:51:36

1

这是基于埃文卡罗尔的回答,但我要详细说明这种情况对其他人有用。我剔除了响应部分;我怀疑我的部分代码会很有趣。

#!/usr/bin/perl -w 

require HTTP::Date; 
require LWP::UserAgent; 
require Date::Parse; 

my $lastChecked = '2009-01-01'; 
my $ua = LWP::UserAgent->new; 
$ua->default_header('If-Modified-Since' => HTTP::Date::time2str(Date::Parse::str2time($lastChecked))); 

my $response = $ua->get('http://example.com/'); 

if ($response->code == 304) { 
    print "No changes.\n"; 
} elsif ($response->is_success) { 
    print $response->decoded_content; 
} else { 
    print "Response was error " . $response->code . ": '" . $response->status_line . "'\n"; 
}