Add a photo.
To avoid limitations on HTTP POST maximum size, the pwg.images.add was “splitted” into several calls to pwg.images.addChunk and then a single call to pwg.images.add.
To avoid high CPU usage on server side, the photo must be resized on sender side, at least in 2 sizes : the thumbnail and the “web resized” photo. You can optionally send a “high resolution” photo.
pwg.images.addChunk adds a chunk in the “upload/buffer” directory. The uploaded chunk filename follows the following format: <original_sum>-<type>-<position>.block
Tip: 500KB is a good size for a chunk, don't go too high because you'll encounter problems related to POST maximum size, don't go too low because you'll take more time to perform the numerous requests than really sending the chunked content.
Now that thumbnail, web resized and optionnaly the high resolution chunks have been added, pwg.images.add merge the chunks, copy the produced files into their final directory, checks the produced files against their expected md5sums, register the photo in the database.
piwigo-remote.pl is included into Piwigo. You can found this script in the “tools” directory.
#!/usr/bin/perl #### # Usage examples # # time perl piwigo_remote.pl \ # --file=erwann_rocher-web.jpg \ # --define categories=9 \ # --chunk_size=200_000 use strict; use warnings; use JSON; use LWP::UserAgent; use Getopt::Long; use Encode qw/is_utf8 decode/; use POSIX qw(ceil floor); my %opt = (); GetOptions( \%opt, qw/action=s file=s categories=s chunk_size=i define=s%/ ); our $ua = LWP::UserAgent->new; $ua->cookie_jar({}); my %conf; $conf{base_url} = 'http://localhost/piwigo/dev/branches/2.7'; $conf{response_format} = 'json'; $conf{username} = 'plg'; $conf{password} = 'plg'; $conf{chunk_size} = defined $opt{chunk_size} ? $opt{chunk_size} : 500_000; my $result = undef; my $query = undef; binmode STDOUT, ":encoding(utf-8)"; # TODO : don't connect at each script call, use the session duration instead. my $form = { method => 'pwg.session.login', username => $conf{username}, password => $conf{password}, }; $result = $ua->post( $conf{base_url}.'/ws.php?format=json', $form ); use MIME::Base64 qw(encode_base64); use Digest::MD5::File qw/file_md5_hex/; use File::Slurp; $form = {}; $form->{method} = 'pwg.images.add'; my $original_sum = file_md5_hex($opt{file}); $form->{original_sum} = $original_sum; send_chunks( filepath => $opt{file}, type => 'file', original_sum => $original_sum, ); foreach my $key (keys %{ $opt{define} }) { $form->{$key} = $opt{define}{$key}; } my $response = $ua->post( $conf{base_url}.'/ws.php?format=json', $form ); print "-" x 50, "\n"; printf("response code : %u\n", $response->code); printf("response message : %s\n", $response->message); print "-" x 50, "\n"; print "\n"; if ($response->is_success) { print "upload successful\n"; } else { warn 'A problem has occured during upload', "\n"; warn $response->decoded_content, "\n"; die $response->status_line; } $query = pwg_ws_get_query( method => 'pwg.session.logout' ); $ua->get($query); sub pwg_ws_get_query { my %params = @_; my $query = $conf{base_url}.'/ws.php?format='.$conf{response_format}; foreach my $key (keys %params) { $query .= '&'.$key.'='.$params{$key}; } return $query; } sub send_chunks { my %params = @_; use MIME::Base64 qw(encode_base64); use File::Slurp; my $content = read_file($params{filepath}); my $content_length = length($content); my $nb_chunks = ceil($content_length / $conf{chunk_size}); my $chunk_pos = 0; my $chunk_id = 1; while ($chunk_pos < $content_length) { my $chunk = substr( $content, $chunk_pos, $conf{chunk_size} ); $chunk_pos += $conf{chunk_size}; my $response = $ua->post( $conf{base_url}.'/ws.php?format=json', { method => 'pwg.images.addChunk', data => encode_base64($chunk), original_sum => $params{original_sum}, position => $chunk_id, type => $params{type}, } ); printf( 'chunk %05u of %05u for %s "%s"'."\n", $chunk_id, $nb_chunks, $params{type}, $params{filepath} ); if ($response->code != 200) { printf("response code : %u\n", $response->code); printf("response message : %s\n", $response->message); } $chunk_id++; } }