need trigger to trick file name on download #1728

Closed
opened 2026-10-05 00:54:21 +02:00 by adam · 0 comments
Owner

When downloading a format, the name is <base name>.format_ext and sometimes it is not name you want for your file. Here is the case I've been working on : a user has the following files :

CMYK_basename.pdf
RGB_basename.svg
RGB_basename@3xblue.png
RGB_basename@3xwhite.png
Adobe_basename.svg
Adobe_basename@3xwhite.png
Adobe_basename@3xblue.png

where RGB_basename@3xblue.png is used as base file and others as formats. With the implementation of format files automatic detection (see API method pwg.images.formats.searchImage), it is not possible to detect Adobe_basename@3xwhite.png as format of RGB_basename@3xblue.png. So I had to implement a "live rename" of the posted file name during check and upload :

add_event_handler('init', 'custom_plugin_init');
function custom_plugin_init()
{
  global $template, $conf;

  if (
    'ws' == script_basename()
    and isset($_REQUEST['method'])
    and 'pwg.images.formats.searchImage' == $_REQUEST['method']
    and isset($_POST['filename_list'])
  )
  {
    $candidates = json_decode(stripslashes($_POST['filename_list']), true);
    foreach ($candidates as $format_external_id => $format_filename)
    {
      $candidates[$format_external_id] = custom_plugin_format_rename_input($format_filename);
    }
    $_POST['filename_list'] = json_encode($candidates);
  }

  if (
    'ws' == script_basename()
    and isset($_REQUEST['method'])
    and 'pwg.images.upload' == $_REQUEST['method']
    and isset($_POST['name'])
  )
  {
    $_POST['name'] = custom_plugin_format_rename_input($_POST['name']);
  }
}

function custom_plugin_format_rename_input($input_name)
{
  $new_name = $input_name;

  // RGB_basename@3xblue.png => base file
  // 
  // CMYK_basename.pdf           => RGB_basename@3xblue.print.pdf
  // RGB_basename.svg            => RGB_basename@3xblue.rgb.svg
  // RGB_basename@3xblue.png     => RGB_basename@3xblue.rgb.blue.png
  // RGB_basename@3xwhite.png    => RGB_basename@3xblue.rgb.white.png
  // Adobe_basename.svg          => RGB_basename@3xblue.adobe.svg
  // Adobe_basename@3xwhite.png  => RGB_basename@3xblue.adobe.white.png
  // Adobe_basename@3xblue.png   => RGB_basename@3xblue.adobe.blue.png

  if (preg_match('/(CMYK|RGB|Adobe)_(\w+)(\.pdf|\.svg|@3xwhite\.png|@3xblue\.png)$/', $input_name, $matches))
  {
    $pattern_to_template = array(
      'CMYK#.pdf'            => 'RGB_%s@3xblue.print.pdf',
      'RGB#.svg'             => 'RGB_%s@3xblue.rgb.svg',
      'RGB#@3xwhite.png'     => 'RGB_%s@3xblue.rgb.white.png',
      'Adobe#.svg'           => 'RGB_%s@3xblue.adobe.svg',
      'Adobe#@3xwhite.png'   => 'RGB_%s@3xblue.adobe.white.png',
      'Adobe#@3xblue.png'    => 'RGB_%s@3xblue.adobe.blue.png',
    );

    $key = $matches[1].'#'.$matches[3];
    if (isset($pattern_to_template[$key]))
    {
      $new_name = sprintf($pattern_to_template[$key], $matches[2]);
    }
  }

  return $new_name;
}

That's enough for the input of formats, but when you download, you get RGB_basename@3xblue.adobe.blue.png instead of Adobe_basename@3xblue.png as provided during upload.

So I need a trigger loc_action_before_http_headers in action.php to be able to write:

add_event_handler('loc_action_before_http_headers', 'custom_plugin_loc_action_before_http_headers');
function custom_plugin_loc_action_before_http_headers()
{
  global $element_info;

  // RGB_basename@3xblue.print.pdf        => CMYK_basename.pdf
  // RGB_basename@3xblue.rgb.svg          => RGB_basename.svg
  // RGB_basename@3xblue.rgb.white.png    => RGB_basename@3xwhite.png
  // RGB_basename@3xblue.adobe.svg        => Adobe_basename.svg
  // RGB_basename@3xblue.adobe.white.png  => Adobe_basename@3xwhite.png
  // RGB_basename@3xblue.adobe.blue.png   => Adobe_basename@3xblue.png

  $ext_to_pattern = array(
    'print.pdf'       => 'CMYK_%s.pdf',
    'rgb.svg'         => 'RGB_%s.svg',
    'rgb.white.png'   => 'RGB_%s@3xwhite.png',
    'adobe.svg'       => 'Adobe_%s.svg',
    'adobe.white.png' => 'Adobe_%s@3xwhite.png',
    'adobe.blue.png'  => 'Adobe_%s@3xblue.png',
  );

  if (preg_match('/^RGB_(.+)@3xblue\.('.implode('|', array_map(function ($a) { return preg_quote($a); }, array_keys($ext_to_pattern))).')$/', $element_info['file'], $matches))
  {
    $element_info['file'] = sprintf($ext_to_pattern[ $matches[2] ], $matches[1]);
  }
}

By the way, here is the appropriate piece of local configuration:

$conf['enable_formats'] = true;
$conf['format_ext'] = array(
  'rgb.white.png',
  'rgb.svg',
  'adobe.blue.png',
  'adobe.white.png',
  'adobe.svg',
  'print.pdf',
  'png', // to let the upload format accept *@3xblue.png / *@3xwhite.png
  'svg', // to let the upload format accept *.svg
  'pdf', // to let the upload format accept *.pdf
);

Let's add this trigger loc_action_before_http_headers :-)

When downloading a format, the name is `<base name>.format_ext` and sometimes it is not name you want for your file. Here is the case I've been working on : a user has the following files : ``` CMYK_basename.pdf RGB_basename.svg RGB_basename@3xblue.png RGB_basename@3xwhite.png Adobe_basename.svg Adobe_basename@3xwhite.png Adobe_basename@3xblue.png ``` where `RGB_basename@3xblue.png` is used as base file and others as formats. With the implementation of format files automatic detection (see API method `pwg.images.formats.searchImage`), it is not possible to detect `Adobe_basename@3xwhite.png` as format of `RGB_basename@3xblue.png`. So I had to implement a "live rename" of the posted file name during check and upload : ``` add_event_handler('init', 'custom_plugin_init'); function custom_plugin_init() { global $template, $conf; if ( 'ws' == script_basename() and isset($_REQUEST['method']) and 'pwg.images.formats.searchImage' == $_REQUEST['method'] and isset($_POST['filename_list']) ) { $candidates = json_decode(stripslashes($_POST['filename_list']), true); foreach ($candidates as $format_external_id => $format_filename) { $candidates[$format_external_id] = custom_plugin_format_rename_input($format_filename); } $_POST['filename_list'] = json_encode($candidates); } if ( 'ws' == script_basename() and isset($_REQUEST['method']) and 'pwg.images.upload' == $_REQUEST['method'] and isset($_POST['name']) ) { $_POST['name'] = custom_plugin_format_rename_input($_POST['name']); } } function custom_plugin_format_rename_input($input_name) { $new_name = $input_name; // RGB_basename@3xblue.png => base file // // CMYK_basename.pdf => RGB_basename@3xblue.print.pdf // RGB_basename.svg => RGB_basename@3xblue.rgb.svg // RGB_basename@3xblue.png => RGB_basename@3xblue.rgb.blue.png // RGB_basename@3xwhite.png => RGB_basename@3xblue.rgb.white.png // Adobe_basename.svg => RGB_basename@3xblue.adobe.svg // Adobe_basename@3xwhite.png => RGB_basename@3xblue.adobe.white.png // Adobe_basename@3xblue.png => RGB_basename@3xblue.adobe.blue.png if (preg_match('/(CMYK|RGB|Adobe)_(\w+)(\.pdf|\.svg|@3xwhite\.png|@3xblue\.png)$/', $input_name, $matches)) { $pattern_to_template = array( 'CMYK#.pdf' => 'RGB_%s@3xblue.print.pdf', 'RGB#.svg' => 'RGB_%s@3xblue.rgb.svg', 'RGB#@3xwhite.png' => 'RGB_%s@3xblue.rgb.white.png', 'Adobe#.svg' => 'RGB_%s@3xblue.adobe.svg', 'Adobe#@3xwhite.png' => 'RGB_%s@3xblue.adobe.white.png', 'Adobe#@3xblue.png' => 'RGB_%s@3xblue.adobe.blue.png', ); $key = $matches[1].'#'.$matches[3]; if (isset($pattern_to_template[$key])) { $new_name = sprintf($pattern_to_template[$key], $matches[2]); } } return $new_name; } ``` That's enough for the input of formats, but when you download, you get `RGB_basename@3xblue.adobe.blue.png` instead of `Adobe_basename@3xblue.png` as provided during upload. So I need a trigger `loc_action_before_http_headers` in `action.php` to be able to write: ``` add_event_handler('loc_action_before_http_headers', 'custom_plugin_loc_action_before_http_headers'); function custom_plugin_loc_action_before_http_headers() { global $element_info; // RGB_basename@3xblue.print.pdf => CMYK_basename.pdf // RGB_basename@3xblue.rgb.svg => RGB_basename.svg // RGB_basename@3xblue.rgb.white.png => RGB_basename@3xwhite.png // RGB_basename@3xblue.adobe.svg => Adobe_basename.svg // RGB_basename@3xblue.adobe.white.png => Adobe_basename@3xwhite.png // RGB_basename@3xblue.adobe.blue.png => Adobe_basename@3xblue.png $ext_to_pattern = array( 'print.pdf' => 'CMYK_%s.pdf', 'rgb.svg' => 'RGB_%s.svg', 'rgb.white.png' => 'RGB_%s@3xwhite.png', 'adobe.svg' => 'Adobe_%s.svg', 'adobe.white.png' => 'Adobe_%s@3xwhite.png', 'adobe.blue.png' => 'Adobe_%s@3xblue.png', ); if (preg_match('/^RGB_(.+)@3xblue\.('.implode('|', array_map(function ($a) { return preg_quote($a); }, array_keys($ext_to_pattern))).')$/', $element_info['file'], $matches)) { $element_info['file'] = sprintf($ext_to_pattern[ $matches[2] ], $matches[1]); } } ``` By the way, here is the appropriate piece of local configuration: ``` $conf['enable_formats'] = true; $conf['format_ext'] = array( 'rgb.white.png', 'rgb.svg', 'adobe.blue.png', 'adobe.white.png', 'adobe.svg', 'print.pdf', 'png', // to let the upload format accept *@3xblue.png / *@3xwhite.png 'svg', // to let the upload format accept *.svg 'pdf', // to let the upload format accept *.pdf ); ``` Let's add this trigger `loc_action_before_http_headers` :-) <!-- github-sync-id:1887934482 -->
adam closed this issue 2026-10-05 00:54:21 +02:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: adam/Piwigo#1728