简体   繁体   English

perl保存lwp下载的文件

[英]perl save a file downloaded by lwp

Im using LWP to download an executable file type and with the response in memory, i am able to hash the file. 我使用LWP下载可执行文件类型并在内存中响应,我能够散列文件。 However how can i save this file on my system? 但是,如何在我的系统上保存此文件? I think i'm on the wrong track with what i'm trying below. 我想我在下面尝试的是错误的轨道。 The download is successful as i am able to generate the hash correctly (I've double checked it by downloading the actual file and comparing the hashes). 下载成功,因为我能够正确生成哈希(我通过下载实际文件并比较哈希来仔细检查它)。

use strict;
use warnings;
use LWP::Useragent;
use Digest::MD5    qw( md5_hex );
use Digest::MD5::File qw( file_md5_hex );
use File::Fetch;

my $url = 'http://www.karenware.com/progs/pthasher-setup.exe';
my $filename = $url;
$filename =~ m/.*\/(.*)$/;
$filename = $1;
my $dir ='/download/two';
print "$filename\n";

my $ua = LWP::UserAgent->new();
my $response = $ua->get($url);
die $response->status_line if !$response->is_success;
my $file = $response->decoded_content( charset => 'none' );
my $md5_hex = md5_hex($file);
print "$md5_hex\n";
my $save = "Downloaded/$filename";
    unless(open SAVE, '>>'.$save) {
        die "\nCannot create save file '$save'\n";
    }
    print SAVE $file;
    close SAVE;

If you are wondering why do i not instead download everything then parse the folder for each file and hash, its because im downloading all these files in a loop. 如果你想知道我为什么不下载所有内容然后解析每个文件和哈希的文件夹,因为我在循环中下载所有这些文件。 And during each loop, i upload the relevant source URL (where this file was found) , along with the file name and hash into a database at one go. 在每个循环中,我将相关的源URL(找到此文件的位置)以及文件名和哈希一次性上传到数据库中。

Try getstore() from LWP::Simple LWP::Simple尝试getstore()

use strict;
use warnings;
use LWP::Simple qw(getstore);
use LWP::UserAgent;
use Digest::MD5    qw( md5_hex );
use Digest::MD5::File qw( file_md5_hex );
use File::Fetch;

my $url = 'http://www.karenware.com/progs/pthasher-setup.exe';
my $filename = $url;
$filename =~ m/.*\/(.*)$/;
$filename = $1;
my $dir ='/download/two';
print "$filename\n";

my $ua = LWP::UserAgent->new();
my $response = $ua->get($url);
die $response->status_line if !$response->is_success;
my $file = $response->decoded_content( charset => 'none' );
my $md5_hex = md5_hex($file);
print "$md5_hex\n";
my $save = "Downloaded/$filename";
getstore($url,$save);

getstore is an excellent solution, however for anyone else reading this response in a slightly different setup, it may not solve the issue. getstore是一个很好的解决方案,但对于其他人在稍微不同的设置中阅读此响应,它可能无法解决问题。

First of all, you could quite possibly just be suffering from a binary/text issue. 首先,你很可能只是遇到二进制/文本问题。

I'd change 我改变了

my $save = "Downloaded/$filename";
unless(open SAVE, '>>'.$save) {
    die "\nCannot create save file '$save'\n";
}
print SAVE $file;
close SAVE;

to

my $save = "Downloaded/$filename";
open my $fh, '>>', $save or die "\nCannot create save file '$save' because $!\n";
# on platforms where this matters
# (like Windows) this is needed for 
# 'binary' files:
binmode $fh;
print $fh $file;
close $fh;

The reason I like this better is that if you have set or acquired some settings on your browser object ($ua), they are ignored in LWP::Simple's getstore, as it uses its own browser. 我更喜欢这个的原因是,如果你在浏览器对象($ ua)上设置或获取了一些设置,它们会在LWP :: Simple的getstore中被忽略,因为它使用自己的浏览器。

Also, it uses the three parameter version of open which should be safer. 此外,它使用open的三个参数版本,它应该更安全。

Another solution would be to use the callback method and store the file while you are downloading it, if for example you are dealing with a large file. 另一个解决方案是使用回调方法并在下载文件时存储文件,例如,如果您正在处理大文件。 The hashing algorithm would have to be changed so it is probably not relevant here but here's a sample: 必须更改散列算法,因此它可能与此不相关,但这里是一个示例:

my $req = HTTP::Request->new(GET => $uri);
open(my $fh, '>', $filename) or die "Could not write to '$filename': $!";
binmode $fh;
$res = $ua->request($req, sub {
    my ($data, $response, $protocol) = @_;
    print $fh $data;
});
close $fh;

And if the size is unimportant (and the hashing is done some other way) you could just ask your browser to store it directly: 如果大小不重要(并且以其他方式完成散列),您可以直接让浏览器存储它:

my $req = HTTP::Request->new(GET => $uri);
$res = $ua->request($req, $filename);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM