Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Per FTP

3 réponses
Avatar
Frantz Dorsemaine
Bonjour a tous,


Je shouaire recuperer un fichier sur un serveur FTP par Perl, ca c'est pas
un probleme. Mais peut-on le recuperer par tranche de 1MO par exemple.


Le fichier fait 100MO, mais je veux le télécharger par tranche de 1MO de
façon à pouvoir reprendre le téléchargement sur plusieur jour si nécéssaire
ou alors faire en sorte de reprendre à l'endroit ou cela c'est arrêter.

Si vous avez une idée ;-)

Meric A+

Frantz

3 réponses

Avatar
jl_morel
Dans l'article ,
a dit...

Je shouaire recuperer un fichier sur un serveur FTP par Perl, ca c'est pas
un probleme. Mais peut-on le recuperer par tranche de 1MO par exemple.


Le fichier fait 100MO, mais je veux le télécharger par tranche de 1MO de
façon à pouvoir reprendre le téléchargement sur plusieur jour si nécéssaire
ou alors faire en sorte de reprendre à l'endroit ou cela c'est arrêter.



Ce n'est pas facile à faire.

Le module Net::FTP a bien une méthode
get( REMOTE_FILE [, LOCAL_FILE [, WHERE]])
qui permet de commencer le téléchargement à l'offset WHERE, mais rien ne
permet d'arrêter le transfert quand une certaine taille est atteinte.

J'ai modifié la méthode get en une méthode get_part qui prend les mêmes
paramètres plus un : la taille du morceau de fichier que l'on désire :

get_part( REMOTE_FILE, LOCAL_FILE, WHERE, SIZE )
ajoute à la fin du fichier LOCAL_FILE la partie de REMOTE_FILE qui commence
à l'offset WHERE et de taille SIZE. La méthode renvoie l'offset du morceau
suivant, si on veut continuer (ou undef en cas d'erreur). Quand l'offset est
supérieur ou égal à la taille du fichier, tout le fichier est chargé. Le
tranfert est toujours en mode binary pour éviter les problèmes de CR/LF.

Le petit script suivant teste la fonction en comparant les fichiers obtenus
par get et get_part.

HTH

#!/usr/bin/perl
use strict;
use warnings;
use Net::FTP;

#====== Ajout d'une méthode get_part à Net::FTP
package Net::FTP;

sub get_part {
my ( $ftp, $remote, $local, $where, $part_size ) = @_;
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 =~ /[rn]/s;

$ftp->binary;
${*$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_APPEND: 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 $blksize = ${*$ftp}{'net_ftp_blksize'};
local $; # Just in case

while (1) {
$blksize = $part_size if ( $part_size < $blksize );
last unless $len = $data->read( $buf, $blksize );
$where += $len;

if ( trEBCDIC && $ftp->type ne 'I' ) {
$buf = $ftp->toebcdic($buf);
$len = length($buf);
}

unless ( print $loc $buf ) {
carp "Cannot write to Local file $local: $!n";
$data->abort;
close($loc) unless $localfd;
return undef;
}
last unless $part_size -= $len;
}
close($loc) unless ($localfd);
$data->abort();
return $where;
}

package main;

#====== Fin de la méthode get_part ajoutée à Net::FTP

# programme de test

use File::Compare;
$|++;

my $ftp = Net::FTP->new('ftp.perl.org') or die $!;
$ftp->login('anonymous') or die $!;
$ftp->cwd('pub/cpan') or die $!;

$ftp->binary;
$ftp->get('RECENT.html'); # téléchargement en une partie

my $filesize = $ftp->size('RECENT.html');
my $offset = 0;

while ( $offset < $filesize ) { # téléchargement en parties de 50 ko
print "$offsetn";
$offset = $ftp->get_part('RECENT.html', # fichier cible
'RECENT2.html', # fichier local
$offset,
50 * 1024 # = 50 ko
);
}

$ftp->quit;

print "Les fichiers sont ",
compare('RECENT.html', 'RECENT2.html')?"differents !":"identiques !";

__END__


--
J-L.M.
http://www.bribes.org/perl

Avatar
Frantz Dorsemaine
(Jean-Louis MOREL) écrivait
news:45d9f9d9$0$15207$:

Dans l'article ,
a dit...

Je shouaire recuperer un fichier sur un serveur FTP par Perl, ca c'est
pas un probleme. Mais peut-on le recuperer par tranche de 1MO par
exemple.


Le fichier fait 100MO, mais je veux le télécharger par tranche de 1MO
de façon à pouvoir reprendre le téléchargement sur plusieur jour si
nécéssaire ou alors faire en sorte de reprendre à l'endroit ou cela
c'est arrêter.



Ce n'est pas facile à faire.

Le module Net::FTP a bien une méthode
get( REMOTE_FILE [, LOCAL_FILE [, WHERE]])
qui permet de commencer le téléchargement à l'offset WHERE, mais rien
ne permet d'arrêter le transfert quand une certaine taille est
atteinte.

J'ai modifié la méthode get en une méthode get_part qui prend les
mêmes paramètres plus un : la taille du morceau de fichier que l'on
désire :

get_part( REMOTE_FILE, LOCAL_FILE, WHERE, SIZE )
ajoute à la fin du fichier LOCAL_FILE la partie de REMOTE_FILE qui
commence à l'offset WHERE et de taille SIZE. La méthode renvoie
l'offset du morceau suivant, si on veut continuer (ou undef en cas
d'erreur). Quand l'offset est supérieur ou égal à la taille du
fichier, tout le fichier est chargé. Le tranfert est toujours en mode
binary pour éviter les problèmes de CR/LF.

Le petit script suivant teste la fonction en comparant les fichiers
obtenus par get et get_part.

HTH

#!/usr/bin/perl
use strict;
use warnings;
use Net::FTP;

#====== Ajout d'une méthode get_part à Net::FTP
package Net::FTP;

sub get_part {
my ( $ftp, $remote, $local, $where, $part_size ) = @_;
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 =~ /[rn]/s;

$ftp->binary;
${*$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_APPEND: 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 $blksize = ${*$ftp}{'net_ftp_blksize'};
local $; # Just in case

while (1) {
$blksize = $part_size if ( $part_size < $blksize );
last unless $len = $data->read( $buf, $blksize );
$where += $len;

if ( trEBCDIC && $ftp->type ne 'I' ) {
$buf = $ftp->toebcdic($buf);
$len = length($buf);
}

unless ( print $loc $buf ) {
carp "Cannot write to Local file $local: $!n";
$data->abort;
close($loc) unless $localfd;
return undef;
}
last unless $part_size -= $len;
}
close($loc) unless ($localfd);
$data->abort();
return $where;
}

package main;

#====== Fin de la méthode get_part ajoutée à Net::FTP

# programme de test

use File::Compare;
$|++;

my $ftp = Net::FTP->new('ftp.perl.org') or die $!;
$ftp->login('anonymous') or die $!;
$ftp->cwd('pub/cpan') or die $!;

$ftp->binary;
$ftp->get('RECENT.html'); # téléchargement en une partie

my $filesize = $ftp->size('RECENT.html');
my $offset = 0;

while ( $offset < $filesize ) { # téléchargement en parties de 50 ko
print "$offsetn";
$offset = $ftp->get_part('RECENT.html', # fichier cible
'RECENT2.html', # fichier local
$offset,
50 * 1024 # = 50 ko
);
}

$ftp->quit;

print "Les fichiers sont ",
compare('RECENT.html', 'RECENT2.html')?"differents
!":"identiques !";

__END__




Bonsoir,

Merci pour la réponse qui marche mais je n'ai pas tout a fait le résultat
escompté.
Si j'interrompt le téléchargement, et que je le relance, il repart a
zéro. Il y à t-il un moyen de repartir de là ou on c'est arrêter.


Avatar
Frantz Dorsemaine
Frantz Dorsemaine écrivait
news::

(Jean-Louis MOREL) écrivait
news:45d9f9d9$0$15207$:

Dans l'article ,
a dit...

Je shouaire recuperer un fichier sur un serveur FTP par Perl, ca
c'est pas un probleme. Mais peut-on le recuperer par tranche de 1MO
par exemple.


Le fichier fait 100MO, mais je veux le télécharger par tranche de 1MO
de façon à pouvoir reprendre le téléchargement sur plusieur jour si
nécéssaire ou alors faire en sorte de reprendre à l'endroit ou cela
c'est arrêter.



Ce n'est pas facile à faire.

Le module Net::FTP a bien une méthode
get( REMOTE_FILE [, LOCAL_FILE [, WHERE]])
qui permet de commencer le téléchargement à l'offset WHERE, mais rien
ne permet d'arrêter le transfert quand une certaine taille est
atteinte.

J'ai modifié la méthode get en une méthode get_part qui prend les
mêmes paramètres plus un : la taille du morceau de fichier que l'on
désire :

get_part( REMOTE_FILE, LOCAL_FILE, WHERE, SIZE )
ajoute à la fin du fichier LOCAL_FILE la partie de REMOTE_FILE qui
commence à l'offset WHERE et de taille SIZE. La méthode renvoie
l'offset du morceau suivant, si on veut continuer (ou undef en cas
d'erreur). Quand l'offset est supérieur ou égal à la taille du
fichier, tout le fichier est chargé. Le tranfert est toujours en mode
binary pour éviter les problèmes de CR/LF.

Le petit script suivant teste la fonction en comparant les fichiers
obtenus par get et get_part.

HTH

#!/usr/bin/perl
use strict;
use warnings;
use Net::FTP;

#====== Ajout d'une méthode get_part à Net::FTP
package Net::FTP;

sub get_part {
my ( $ftp, $remote, $local, $where, $part_size ) = @_;
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 =~ /[rn]/s;

$ftp->binary;
${*$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_APPEND: 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 $blksize = ${*$ftp}{'net_ftp_blksize'};
local $; # Just in case

while (1) {
$blksize = $part_size if ( $part_size < $blksize );
last unless $len = $data->read( $buf, $blksize );
$where += $len;

if ( trEBCDIC && $ftp->type ne 'I' ) {
$buf = $ftp->toebcdic($buf);
$len = length($buf); }

unless ( print $loc $buf ) {
carp "Cannot write to Local file $local: $!n"; $data->abort;
close($loc) unless $localfd;
return undef; }
last unless $part_size -= $len; }
close($loc) unless ($localfd); $data->abort();
return $where;
}

package main;

#====== Fin de la méthode get_part ajoutée à Net::FTP

# programme de test

use File::Compare; $|++;

my $ftp = Net::FTP->new('ftp.perl.org') or die $!;
$ftp->login('anonymous') or die $!;
$ftp->cwd('pub/cpan') or die $!;

$ftp->binary;
$ftp->get('RECENT.html'); # téléchargement en une partie

my $filesize = $ftp->size('RECENT.html');
my $offset = 0;

while ( $offset < $filesize ) { # téléchargement en parties de 50 ko
print "$offsetn";
$offset = $ftp->get_part('RECENT.html', # fichier cible
'RECENT2.html', # fichier local $offset,
50 * 1024 # = 50 ko ); }

$ftp->quit;

print "Les fichiers sont ", compare('RECENT.html',
'RECENT2.html')?"differents
!":"identiques !";

__END__




Bonsoir,

Merci pour la réponse qui marche mais je n'ai pas tout a fait le
résultat escompté.
Si j'interrompt le téléchargement, et que je le relance, il repart a
zéro. Il y à t-il un moyen de repartir de là ou on c'est arrêter.



J'ai trouvé, il suffit de reprer la derniere taille de l'offset et le
tour est joué.

Merci Beaucoup.
Frantz DORSEMAINE