isync has asked for the wisdom of the Perl Monks concerning the following question:

Is there a way to easily trick Net::FTP / Net::FTP::Recursive into only getting the first few bytes of a file - without extending the module?

Or why doesn't this work? (Tells me it can't "open Local file"...??)
package Our::Net::FTP::Recursive; use Carp; use base qw(Net::FTP::Recursive); sub get_partial { my ($ftp, $remote, $local, $where, $limit) = @_; my ($loc, $len, $buf, $resp, $data); local *FD; my $localfd = ref($local) || ref(\$local) eq "GLOB"; ($local = $remote) =~ s#^.*/## unless (defined $local); croak("Bad remote filename '$remote'\n") if $remote =~ /[\r\n]/s; ${*$ftp}{'net_ftp_rest'} = $where if defined $where; my $rest = ${*$ftp}{'net_ftp_rest'}; delete ${*$ftp}{'net_ftp_port'}; delete ${*$ftp}{'net_ftp_pasv'}; $data = $ftp->retr($remote) or return undef; if ($localfd) { $loc = $local; } else { $loc = \*FD; unless (sysopen($loc, $local, O_CREAT | O_WRONLY | ($rest ? O_APPE +ND: O_TRUNC))) { carp "Cannot open Local file $local: $!\n"; $data->abort; return undef; } } if ($ftp->type eq 'I' && !binmode($loc)) { carp "Cannot binmode Local file $local: $!\n"; $data->abort; close($loc) unless $localfd; return undef; } $buf = ''; my ($count, $hashh, $hashb, $ref) = (0); ($hashh, $hashb) = @$ref if ($ref = ${*$ftp}{'net_ftp_hash'}); my $blksize = ${*$ftp}{'net_ftp_blksize'}; local $\; # Just in case while (1) { last unless $len = $data->read($buf, $blksize); if (trEBCDIC && $ftp->type ne 'I') { $buf = $ftp->toebcdic($buf); $len = length($buf); } if ($hashh) { $count += $len; print $hashh "#" x (int($count / $hashb)); $count %= $hashb; } unless (print $loc $buf) { carp "Cannot write to Local file $local: $!\n"; $data->abort; close($loc) unless $localfd; return undef; } if($len >= $limit){ $data->abort; close($loc) unless $localfd; return $local; } print "READ: $len\n"; } print $hashh "\n" if $hashh; unless ($localfd) { unless (close($loc)) { carp "Cannot close file $local (perhaps disk space) $!\n"; return undef; } } unless ($data->close()) # implied $ftp->response { carp "Unable to close datastream"; return undef; } return $local; } 1;

Replies are listed 'Best First'.
Re: Easy way to FTP get() only first few bytes?
by charlesboyo (Beadle) on Aug 29, 2011 at 23:35 UTC

    Hmmm, the following reads the first 200 bytes for a given file. Uses the fact that the retr method returns a file handle on which you can call read() with a specific size.

    #!/usr/bin/perl use strict; use Net::FTP; my $ftp = Net::FTP->new("ftp.nai.com") or die "cannot connect: $@\n"; $ftp->login("anonymous",'anon@') or die "Cannot login: ", $ftp->messag +e; #print $ftp->ls or die "ls failed: ", $ftp->message; my $dataconn = $ftp->retr('legal.txt'); my $buffer; my $bytes_read = $dataconn->read($buffer, 200); print $buffer;