Here's a perl upload implementation:
 #!/usr/bin/perl
 
 use JSON;
 use LWP::UserAgent;
 use HTTP::Headers;
 use HTTP::Request;
 sub     upload  {
        my($key, $parent, $filetype, $fileLocation, $filename, $title, $description, $tags) = @_;
        my $entity = {
                name => $filename,
                type => $filetype
        };
        my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
                      $atime,$mtime,$ctime,$blksize,$blocks) = stat($fileLocation);
        open(IMAGE,"<$fileLocation") || die "open: $!";
        my $item;
        my $nread = sysread(IMAGE,$item,$size);
        close(IMAGE);
        my $boundary = "gallery3.upload.$$";
        my $json = JSON->new;
        my $json_entity = $json->encode($entity);
        my(@parts);
        push(@parts,"--$boundary");
        push(@parts,'Content-Disposition: form-data; name="entity"');
        push(@parts,'Content-Type: text/plain; charset=UTF-8');
        push(@parts,'Content-Transfer-Encoding: 8bit');
        push(@parts,"");
        push(@parts,$json_entity);
        push(@parts,"--$boundary");
        push(@parts,'Content-Disposition: form-data; name="file"; filename="'.$filename.'"');
        # G3 rest server only wants application/octet-stream, won't accept real mime type
        push(@parts,'Content-Type: application/octet-stream');
        # G3 rest server  only wants binary, won't parse base64 
        push(@parts,'Content-Transfer-Encoding: binary'); 
        push(@parts,'');
        push(@parts,$item);
        push(@parts,"--$boundary--");
        my $data = join("\n",@parts);
        my $ua = LWP::UserAgent->new;
        my $headers = HTTP::Headers->new;
        $headers->header('X-Gallery-Request-Method' => 'post');
        $headers->header('X-Gallery-Request-Key' => $key);
        $headers->header('Content-Type' => "multipart/form-data; boundary=$boundary");
        $headers->header('Content-Length' => length $data);
        my $request= HTTP::Request->new('POST',$parent,$headers,$data);
        my $result = $ua->request($request);
        $result->content;
 }