Index: /extensions/piwigo_import_tree/piwigo_import_tree.pl
===================================================================
--- /extensions/piwigo_import_tree/piwigo_import_tree.pl	(revision 18576)
+++ /extensions/piwigo_import_tree/piwigo_import_tree.pl	(revision 18577)
@@ -8,5 +8,5 @@
 
 # make it compatible with Windows, but breaks Linux
-use utf8;
+#use utf8;
 
 use File::Find;
@@ -17,4 +17,6 @@
 use Getopt::Long;
 use Encode qw/is_utf8 decode/;
+use Time::HiRes qw/gettimeofday tv_interval/;
+use Digest::MD5 qw/md5 md5_hex/;
 
 my %opt = ();
@@ -29,4 +31,5 @@
           define=s%
           quiet
+          only_write_cache
       /
 );
@@ -200,4 +203,8 @@
     }
 
+    print '[album '.$params{album_id}.'] '.$params{path}.' upload starts... ';
+    $| = 1;
+    my $t1 = [gettimeofday];
+
     piwigo_login();
     my $response = $ua->post(
@@ -206,4 +213,7 @@
         'Content_Type' => 'form-data',
     );
+
+    my $elapsed = tv_interval($t1);
+    print ' upload completed ('.sprintf('%u ms', $elapsed * 1000).')'."\n";
 }
 
@@ -229,6 +239,13 @@
     	foreach my $dir (split '/', $path) {
             if (not defined $piwigo_albums{$up_dir.$dir}) {
-                print 'album "'.$up_dir.$dir.'" must be created'."\n";
-                my $id = add_album(name => $dir, parent => $parent_id);
+                my $id = cached_album(dir => $up_dir.$dir);
+                # if the album is not in the cache OR if the id in the cache
+                # matches no album fetched by pwg.categories.getList, then
+                # we have to create the album first
+                if (not defined $id or not grep($_ eq $id, values(%piwigo_albums))) {
+                    print 'album "'.$up_dir.$dir.'" must be created'."\n";
+                    $id = add_album(name => $dir, parent => $parent_id);
+                    cache_add_album(dir => $up_dir.$dir, id => $id);
+                }
                 $piwigo_albums{$up_dir.$dir} = $id;
             }
@@ -254,7 +271,108 @@
         }
 
-        print $File::Find::name.' must be uploaded in "'.$album_key.'" (id='.$album_id.')'."\n";
+        if (cached_photo(path => $File::Find::name, dir => $album_key)) {
+            return 1;
+        }
+
+        if ($opt{only_write_cache}) {
+            cache_add_photo(path => $File::Find::name, dir => $album_key);
+            return 1;
+        }
+
         add_photo(path => $File::Find::name, album_id => $album_id);
+        cache_add_photo(path => $File::Find::name, dir => $album_key);
         # print 'dirname = '.dirname($path)."\n\n";
     }
 }
+
+sub cache_add_photo {
+    my %params = @_;
+
+    if (cached_photo(path => $params{path}, dir => $params{dir})) {
+        if (not $opt{quiet}) {
+            print 'photo is in the cache, no upload'."\n";
+        }
+        return 1;
+    }
+
+    $params{dir} =~ s{ / }{/}g;
+
+    my $filepath = $params{dir}.'/.piwigo_import_tree.txt';
+
+    open(my $ofh, '>> '.$filepath) or die 'cannot open file "'.$filepath.'" for writing';
+    print {$ofh} $conf{base_url}.' '.md5_hex(basename($params{path}));
+
+    if (defined $params{id}) {
+        print {$ofh} ' [id='.$params{id}.']';
+    }
+
+    print {$ofh} "\n";
+    close($ofh);
+}
+
+sub cached_photo {
+    my %params = @_;
+
+    $params{dir} =~ s{ / }{/}g;
+
+    my $filepath = $params{dir}.'/.piwigo_import_tree.txt';
+
+    if (not -f $filepath) {
+        return undef;
+    }
+
+    my $photo_id = undef;
+    my $photo_filename_md5 = md5_hex(basename($params{path}));
+
+    open(my $ifh, '<'.$filepath) or die 'cannot open file "'.$filepath.'" for reading';
+    while (my $line = <$ifh>) {
+        chomp $line;
+        if ($line =~ m/$photo_filename_md5/) {
+            # TODO if needed : search the [id=(\d+)] for photo_id
+            return 1;
+        }
+    }
+    close($ifh);
+
+    return undef;
+}
+
+sub cache_add_album {
+    my %params = @_;
+
+    $params{dir} =~ s{ / }{/}g;
+
+    my $filepath = $params{dir}.'/.piwigo_import_tree.txt';
+
+    open(my $ofh, '>> '.$filepath) or die 'cannot open file "'.$filepath.'" for writing';
+    print {$ofh} $conf{base_url}.' album_id = '.$params{id}."\n";
+    print $conf{base_url}.' album_id = '.$params{id}."\n";
+    close($ofh);
+}
+
+sub cached_album {
+    my %params = @_;
+
+    $params{dir} =~ s{ / }{/}g;
+
+    my $filepath = $params{dir}.'/.piwigo_import_tree.txt';
+
+    if (not -f $filepath) {
+        return undef;
+    }
+
+    my $album_id = undef;
+
+    open(my $ifh, '<'.$filepath) or die 'cannot open file "'.$filepath.'" for reading';
+    while (my $line = <$ifh>) {
+        chomp $line;
+        if ($line =~ m/album_id = (\d+)/) {
+            $album_id = $1;
+        }
+    }
+    close($ifh);
+
+    print 'directory "'.$params{dir}.'" was found as album '.$album_id."\n";
+
+    return $album_id;
+}
