Answers.Body: <p>Got it working with this:</p>
  <pre><code>Event::on(Asset::class,Element::EVENT_AFTER_SAVE,
    static function (ModelEvent $event) {
      if (Craft::$app-&gt;request-&gt;isSiteRequest) {
        $asset = $event-&gt;sender;
        $folderId = $asset-&gt;getFolder();
        $now = new DateTime();
        $timestamp = $now-&gt;getTimestamp();
        $newAssetTitle = Craft::$app-&gt;getRequest()-&gt;getBodyParam('imageTitle');
        $asset-&gt;title = $newAssetTitle;
        $newAssetFilename = StringHelper::toKebabCase($asset-&gt;title) . '-' . $timestamp . '.' . $asset-&gt;getExtension();
        if (!empty($asset)) {
          Craft::$app-&gt;assets-&gt;moveAsset($asset, $folderId, $newAssetFilename);
        }
      }
    }
  );
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-01-13T05:32:30.747Z
Answers.LastActivityDate: 2023-01-13T05:32:30.747Z
Answers.UserDisplayName: supazu
Answers.Body: <p>I just found a very nice solution for changing the filename usind the <code>Assets::EVENT_SET_FILENAME</code> event:</p>
  <pre><code>Event::on(Assets::class, Assets::EVENT_SET_FILENAME, function (SetAssetFilenameEvent $event) {
      $event-&gt;filename = YourHelper::sanitizeFilename($event-&gt;originalFilename);
  });
  </code></pre>
  <p>where <code>YourHelper::sanitizeFilename(...)</code> is a placeholder function for your own modifier.</p>
  <p>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:</p>
  <ul>
  <li>MacOS sometimes seems to use a so called &quot;Trema&quot; character to map Umlaute into filenames instead of using UTF-8 Umlaute.</li>
  <li>The &quot;Trema&quot; character is a horizontal colon placed above the previous character.</li>
  <li>In order to correctly convert those Umlaute into ASCII, it's easy to replace the &quot;Trema&quot; character with an &quot;e&quot; to achieve the same result as converting a real UTF-8 Umlaut into its 2 character equivalent.</li>
  </ul>
  <p><code>$filename = str_replace(['Ä', 'Ö', 'Ü', 'ä', 'ö', 'ü', 'ß', '̈'], ['AE', 'OE', 'UE', 'ae', 'oe', 'ue', 'ss', 'e'], $filename);</code></p>
  <p>Please note: the &quot;Trema&quot; 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 :-)</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-21T13:50:14.293Z
Answers.LastActivityDate: 2023-03-21T13:50:14.293Z
Answers.UserDisplayName: Matthias Redl-Mann
Answers.Body: <p>If you're using Craft 4.0.0 or later, you should be able to use <code>$asset-&gt;setFilename($newAssetFilename)</code> (<a href="https://docs.craftcms.com/api/v4/craft-elements-asset.html#method-setfilename" rel="nofollow noreferrer">docs</a>).</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-01-12T10:56:26.613Z
Answers.Text: Thanks for the reply. Unfortunately, that doesn't seem to do it...
Answers.UserDisplayName: supazu
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-01-12T12:26:12.190Z
Answers.Text: 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](https://docs.craftcms.com/api/v4/craft-services-assets.html#method-moveasset) do suggest it's intended for renaming.
Answers.UserDisplayName: Martin Spain
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-01-12T12:32:07.693Z
Answers.Text: 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.
Answers.UserDisplayName: supazu
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-01-12T09:42:18.153Z
Answers.LastActivityDate: 2023-01-12T09:42:18.153Z
Answers.UserDisplayName: Martin Spain
Body: <p>I'm trying to rename files uploaded by users on the frontend. Changing the title is working, but I can't rename the file.</p>
  <p>Would appreciate some help!</p>
  <pre><code>Event::on(
    Asset::class,Asset::EVENT_BEFORE_HANDLE_FILE,function (AssetEvent $event) {
      if (Craft::$app-&gt;request-&gt;isSiteRequest) {
        $asset = $event-&gt;asset;
        $now = new DateTime();
        $timestamp = $now-&gt;getTimestamp();
  
        $newAssetTitle = Craft::$app-&gt;getRequest()-&gt;getBodyParam('imageTitle');
        $newAssetFilename = StringHelper::toKebabCase($newAssetTitle) . '-' . $timestamp . '.' . $asset-&gt;getExtension();
  
        $asset-&gt;title = $newAssetTitle; // this works
        $asset-&gt;filename = $newAssetFilename; // this doesn't work
      }
    }
  );
  </code></pre>
  
Tags: <assets><modules>
Title: Change asset title and filename on upload
ThreadText: # Change asset title and filename on upload
  
  (Asked by: username_0 on 2023-01-12)
  
  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
      }
    }
  );
  
  ```
  
  **Tags:** assets, modules
  
  
  ---
  
  ## 3 answers
  
  ### Answer by username_0 on 2023-01-13. Score: 1 | Accepted answer
  
  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);
        }
      }
    }
  );
  
  ```
  
  
  ---
  
  ### Answer by username_1 on 2023-03-21. Score: 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 :-)
  
  
  ---
  
  ### Answer by username_2 on 2023-01-12. Score: 1
  
  If you're using Craft 4.0.0 or later, you should be able to use `$asset->setFilename($newAssetFilename)` ([docs](https://docs.craftcms.com/api/v4/craft-elements-asset.html#method-setfilename)).
  
  > **Comments:**
  > **username_0**: Thanks for the reply. Unfortunately, that doesn't seem to do it...  
  > **username_2**: 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](https://docs.craftcms.com/api/v4/craft-services-assets.html#method-moveasset) do suggest it's intended for renaming.  
  > **username_0**: 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.  
  
  ---
  
  