1

I'm trying to rename files uploaded by users on the frontend. Changing the title is working, but I can't rename the file.

Would appreciate some help!

Event::on(
  Asset::class,Asset::EVENT_BEFORE_HANDLE_FILE,function (AssetEvent $event) {
    if (Craft::$app->request->isSiteRequest) {
      $asset = $event->asset;
      $now = new DateTime();
      $timestamp = $now->getTimestamp();

      $newAssetTitle = Craft::$app->getRequest()->getBodyParam('imageTitle');
      $newAssetFilename = StringHelper::toKebabCase($newAssetTitle) . '-' . $timestamp . '.' . $asset->getExtension();

      $asset->title = $newAssetTitle; // this works
      $asset->filename = $newAssetFilename; // this doesn't work
    }
  }
);

3 Answers 3

2

I just found a very nice solution for changing the filename usind the Assets::EVENT_SET_FILENAME event:

Event::on(Assets::class, Assets::EVENT_SET_FILENAME, function (SetAssetFilenameEvent $event) {
    $event->filename = YourHelper::sanitizeFilename($event->originalFilename);
});

where YourHelper::sanitizeFilename(...) is a placeholder function for your own modifier.

And since I assume that the reason people looking for this issue are sometimes dealing with special characters like e.g. german Umlaute, here is another learning:

  • MacOS sometimes seems to use a so called "Trema" character to map Umlaute into filenames instead of using UTF-8 Umlaute.
  • The "Trema" character is a horizontal colon placed above the previous character.
  • In order to correctly convert those Umlaute into ASCII, it's easy to replace the "Trema" character with an "e" to achieve the same result as converting a real UTF-8 Umlaut into its 2 character equivalent.

$filename = str_replace(['Ä', 'Ö', 'Ü', 'ä', 'ö', 'ü', 'ß', '̈'], ['AE', 'OE', 'UE', 'ae', 'oe', 'ue', 'ss', 'e'], $filename);

Please note: the "Trema" character is the last one in the search array, which is optically placed above the first quotation mark, so it looks like a broken quotation mark or a dirty screen :-)

1

If you're using Craft 4.0.0 or later, you should be able to use $asset->setFilename($newAssetFilename) (docs).

3
  • Thanks for the reply. Unfortunately, that doesn't seem to do it...
    – supazu
    Commented Jan 12, 2023 at 10:56
  • Hmm, that's strange. There's a few issues on SE which suggest using moveAsset to achieve this, which might be worth a try. Something like: Craft::$app->assets->moveAsset($asset, $asset->getFolder(), $newAssetFilename); The docs for moveAsset do suggest it's intended for renaming. Commented Jan 12, 2023 at 12:26
  • I did try that actually, but get Asset is missing its folder ID. I assume that's because it's on EVENT_BEFORE_HANDLE_FILE. I got it working with EVENT_AFTER_SAVE but then renaming the title broke.
    – supazu
    Commented Jan 12, 2023 at 12:32
1

Got it working with this:

Event::on(Asset::class,Element::EVENT_AFTER_SAVE,
  static function (ModelEvent $event) {
    if (Craft::$app->request->isSiteRequest) {
      $asset = $event->sender;
      $folderId = $asset->getFolder();
      $now = new DateTime();
      $timestamp = $now->getTimestamp();
      $newAssetTitle = Craft::$app->getRequest()->getBodyParam('imageTitle');
      $asset->title = $newAssetTitle;
      $newAssetFilename = StringHelper::toKebabCase($asset->title) . '-' . $timestamp . '.' . $asset->getExtension();
      if (!empty($asset)) {
        Craft::$app->assets->moveAsset($asset, $folderId, $newAssetFilename);
      }
    }
  }
);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.