Changeset 3192


Ignore:
Timestamp:
03/13/09 00:09:22 (10 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.