Changeset 3192


Ignore:
Timestamp:
Mar 13, 2009, 12:09:22 AM (15 years ago)
Author:
plg
Message:

bug 941 fixed: to be able to upload heavy photo, chunk the files, send parts
one by one, and then pwg.images.add merge chunks together. Now big uploads
works and you can even have a fine progress bar on client side.

Location:
branches/2.0
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/2.0/include/ws_functions.inc.php

    r3147 r3192  
    880880}
    881881
     882function ws_images_add_chunk($params, &$service)
     883{
     884  // data
     885  // original_sum
     886  // type {thumb, file, high}
     887  // position
     888 
     889  if (!is_admin() || is_adviser() )
     890  {
     891    return new PwgError(401, 'Access denied');
     892  }
     893
     894  $upload_dir = PHPWG_ROOT_PATH.'upload/buffer';
     895
     896  // create the upload directory tree if not exists
     897  if (!is_dir($upload_dir)) {
     898    umask(0000);
     899    $recursive = true;
     900    if (!@mkdir($upload_dir, 0777, $recursive))
     901    {
     902      return new PwgError(500, 'error during buffer directory creation');
     903    }
     904  }
     905
     906  if (!is_writable($upload_dir))
     907  {
     908    // last chance to make the directory writable
     909    @chmod($upload_dir, 0777);
     910
     911    if (!is_writable($upload_dir))
     912    {
     913      return new PwgError(500, 'buffer directory has no write access');
     914    }
     915  }
     916
     917  secure_directory($upload_dir);
     918
     919  $filename = sprintf(
     920    '%s-%s-%05u.block',
     921    $params['original_sum'],
     922    $params['type'],
     923    $params['position']
     924    );
     925
     926  $bytes_written = file_put_contents(
     927    $upload_dir.'/'.$filename,
     928    $params['data']
     929    );
     930
     931  if (false === $bytes_written) {
     932    return new PwgError(
     933      500,
     934      'an error has occured while writting chunk '.$params['position'].' for '.$params['type']
     935      );
     936  }
     937}
     938
     939function merge_chunks($output_filepath, $original_sum, $type)
     940{
     941  ws_logfile('[merge_chunks] input parameter $output_filepath : '.$output_filepath);
     942
     943  $upload_dir = PHPWG_ROOT_PATH.'upload/buffer';
     944  $pattern = '/'.$original_sum.'-'.$type.'/';
     945  $chunks = array();
     946 
     947  if ($handle = opendir($upload_dir))
     948  {
     949    while (false !== ($file = readdir($handle)))
     950    {
     951      if (preg_match($pattern, $file))
     952      {
     953        ws_logfile($file);
     954        array_push($chunks, $upload_dir.'/'.$file);
     955      }
     956    }
     957    closedir($handle);
     958  }
     959
     960  sort($chunks);
     961 
     962  $string = null;
     963  foreach ($chunks as $chunk) {
     964    $string.= file_get_contents($chunk);
     965    unlink($chunk);
     966  }
     967  if (!file_put_contents($output_filepath, base64_decode($string)))
     968  {
     969    return new PwgError(500, 'error while merging chunks for '.$output_filepath);
     970  }
     971 
     972}
     973
    882974function ws_images_add($params, &$service)
    883975{
     
    9571049  $file_path = $upload_dir.'/'.$filename_wo_ext.'.jpg';
    9581050
    959   // dump the photo file
    960   $fh_file = fopen($file_path, 'w');
    961   if (!fwrite($fh_file, base64_decode($params['file_content'])))
    962   {
    963     return new PwgError(500, 'error while writing file');
    964   }
    965   fclose($fh_file);
     1051  // merge the photo file
     1052  merge_chunks($file_path, $params['original_sum'], 'file');
    9661053  chmod($file_path, 0644);
    9671054
     
    10061093    );
    10071094
    1008   // dump the thumbnail
    1009   $fh_thumbnail = fopen($thumbnail_path, 'w');
    1010   if (!fwrite($fh_thumbnail, base64_decode($params['thumbnail_content'])))
    1011   {
    1012     return new PwgError(500, 'error while writing thumbnail');
    1013   }
    1014   fclose($fh_thumbnail);
     1095  // merge the thumbnail
     1096  merge_chunks($thumbnail_path, $params['original_sum'], 'thumb');
    10151097  chmod($thumbnail_path, 0644);
    10161098
     
    10221104
    10231105  // high resolution
    1024   if (isset($params['high_content']))
     1106  if (isset($params['high_sum']))
    10251107  {
    10261108    // high resolution directory is a subdirectory of the photo file, hard
     
    10561138      );
    10571139
    1058     // dump the high resolution file
    1059     $fh_high = fopen($high_path, 'w');
    1060     if (!fwrite($fh_high, base64_decode($params['high_content'])))
    1061     {
    1062       return new PwgError(500, 'error while writing high');
    1063     }
    1064     fclose($fh_high);
     1140    // merge the high resolution file
     1141    merge_chunks($high_path, $params['original_sum'], 'high');
    10651142    chmod($high_path, 0644);
    10661143
     
    11051182  }
    11061183
    1107   if (isset($params['high_content']))
     1184  if (isset($params['high_sum']))
    11081185  {
    11091186    $insert['has_high'] = 'true';
     
    16471724  }
    16481725}
     1726
     1727function ws_logfile($string)
     1728{
     1729  return true;
     1730 
     1731  file_put_contents(
     1732    '/tmp/piwigo_ws.log',
     1733    '['.date('c').'] '.$string."\n",
     1734    FILE_APPEND
     1735    );
     1736}
    16491737?>
  • branches/2.0/tools/piwigo_remote.pl

    r3064 r3192  
    11#!/usr/bin/perl
     2
     3####
     4# Usage examples
     5#
     6# time perl piwigo_remote.pl \
     7#   --action=pwg.images.add \
     8#   --file=erwann_rocher-web.jpg \
     9#   --thumb=erwann_rocher-thumb.jpg \
     10#   --high=erwann_rocher-high.jpg \
     11#   --original=erwann_rocher-high.jpg \
     12#   --define categories=9 \
     13#   --chunk_size=200_000
    214
    315use strict;
     
    820use Getopt::Long;
    921use Encode qw/is_utf8 decode/;
     22use POSIX qw(ceil floor);
    1023
    1124my %opt = ();
    1225GetOptions(
    1326    \%opt,
    14     qw/action=s file=s thumbnail=s high=s original=s categories=s define=s%/
     27    qw/action=s file=s thumbnail=s high=s original=s categories=s chunk_size=i define=s%/
    1528);
    1629
     
    1932
    2033my %conf;
    21 $conf{base_url} = 'http://localhost/~pierrick/piwigo/2.0';
     34$conf{base_url} = 'http://localhost/piwigo/2.0';
    2235$conf{response_format} = 'json';
    23 $conf{username} = 'pierrick';
    24 $conf{password} = 'z0rglub';
     36$conf{username} = 'plg';
     37$conf{password} = 'plg';
    2538$conf{limit} = 10;
     39$conf{chunk_size} = defined $opt{chunk_size} ? $opt{chunk_size} : 500_000;
    2640
    2741my $result = undef;
     
    4963    use File::Slurp;
    5064
     65    $form = {};
     66    $form->{method} = 'pwg.images.add';
     67
    5168    my $original_sum = file_md5_hex($opt{original});
    52 
    53     my $file_content = encode_base64(read_file($opt{file}));
    54     my $file_sum = file_md5_hex($opt{file});
    55 
    56     my $thumbnail_content = encode_base64(read_file($opt{thumbnail}));
    57     my $thumbnail_sum = file_md5_hex($opt{thumbnail});
    58 
    59     $form = {
    60         method => 'pwg.images.add',
     69    $form->{original_sum} = $original_sum;
     70
     71    send_chunks(
     72        filepath => $opt{file},
     73        type => 'file',
    6174        original_sum => $original_sum,
    62         file_sum => $file_sum,
    63         file_content => $file_content,
    64         thumbnail_sum => $thumbnail_sum,
    65         thumbnail_content => $thumbnail_content,
    66         categories => $opt{categories},
    67     };
     75    );
     76    $form->{file_sum} = file_md5_hex($opt{file});
     77
     78    send_chunks(
     79        filepath => $opt{thumbnail},
     80        type => 'thumb',
     81        original_sum => $original_sum,
     82    );
     83    $form->{thumbnail_sum} = file_md5_hex($opt{thumbnail});
    6884
    6985    if (defined $opt{high}) {
    70         $form->{high_content} = encode_base64(read_file($opt{high}));
     86        send_chunks(
     87            filepath => $opt{high},
     88            type => 'high',
     89            original_sum => $original_sum,
     90        );
    7191        $form->{high_sum} = file_md5_hex($opt{high});
    7292    }
     
    232252    return $query;
    233253}
     254
     255sub send_chunks {
     256    my %params = @_;
     257
     258    my $content = encode_base64(read_file($params{filepath}));
     259    my $content_length = length($content);
     260    my $nb_chunks = ceil($content_length / $conf{chunk_size});
     261
     262    my $chunk_pos = 0;
     263    my $chunk_id = 1;
     264    while ($chunk_pos < $content_length) {
     265        my $chunk = substr(
     266            $content,
     267            $chunk_pos,
     268            $conf{chunk_size}
     269        );
     270        $chunk_pos += $conf{chunk_size};
     271
     272        my $response = $ua->post(
     273            $conf{base_url}.'/ws.php?format=json',
     274            {
     275                method => 'pwg.images.addChunk',
     276                data => $chunk,
     277                original_sum => $params{original_sum},
     278                position => $chunk_id,
     279                type => $params{type},
     280            }
     281        );
     282
     283        printf(
     284            'chunk %05u of %05u for %s "%s"'."\n",
     285            $chunk_id,
     286            $nb_chunks,
     287            $params{type},
     288            $params{filepath}
     289        );
     290        if ($response->code != 200) {
     291            printf("response code    : %u\n", $response->code);
     292            printf("response message : %s\n", $response->message);
     293        }
     294
     295        $chunk_id++;
     296    }
     297}
  • branches/2.0/ws.php

    r3064 r3192  
    174174
    175175  $service->addMethod(
     176    'pwg.images.addChunk',
     177    'ws_images_add_chunk',
     178    array(
     179      'data' => array(),
     180      'original_sum' => array(),
     181      'type' => array(),
     182      'position' => array(),
     183      ),
     184    'POST method only. For admin only.'
     185    );
     186 
     187
     188  $service->addMethod(
    176189    'pwg.images.add',
    177190    'ws_images_add',
    178191    array(
    179       'file_content' => array(),
    180192      'file_sum' => array(),
    181       'thumbnail_content' => array(),
    182193      'thumbnail_sum' => array(),
    183       'high_content' => array('default' => null),
    184194      'high_sum' => array('default' => null),
    185195      'original_sum' => array(),
Note: See TracChangeset for help on using the changeset viewer.