Answers.Body: <p>First, when you <a href="https://craftcms.com/docs/plugins/hooks-and-events#listening-for-events" rel="noreferrer">attach event listeners</a> using <code>craft.on</code>, the naming convention for the event name is <code>assets.beforeSaveEntry</code>, not <code>assets.onBeforeSaveEntry</code> (i.e., skip the <code>on</code> part). Both names appear to work, but the former is the one used in the docs and I'd recommend using that.</p>
  
  <p>Second, the reason why your upload "gets stuck" is your call to <code>craft()-&gt;assets-&gt;storeFile</code> inside the event listener. Basically, that call results in a loop, because <code>craft-&gt;assets-&gt;storeFile()</code> will fire another <code>beforeSaveAsset</code> event – making your script execute continually before timing out.</p>
  
  <p>As for actually changing the filename on upload; unfortunately, if there's a reliable way to change the asset filename <em>before the asset is saved</em>, I haven't been able to find it.</p>
  
  <p>However, if you can work with the <code>assets.saveAsset</code> event (which is fired after the asset is uploaded and saved on the server), I found a way:</p>
  
  <p>First, set up an event listener for <code>assets.saveAsset</code>. Inside the event listener, you need to check the <code>$event</code> object's <code>isNewAsset</code> property; making sure the filename is only changed the first time the asset is saved and preventing the loop mentioned above.</p>
  
  <p>Concerning the actual filename, there's a couple of issues to consider. For one, the filename needs to be unique (to that particular folder, as least). If you attempt to store an asset with an existing filename, Craft will use the original filename for your upload (I'd expect Craft to either ask if you wanted to replace the existing file, or suffix the filename with a number, but that doesn't appear to be the case). Secondly, the filename needs to include the file's extension (i.e. <code>jpg</code> or <code>pdf</code>). And finally; because this code runs <em>after</em> the asset has been saved and the file is already stored on the server, it isn't enough to set the filename attribute to the AssetFileModel object (i.e. <code>$asset</code>), you'll also need to rename the actual file.</p>
  
  <p>Keeping these issues in mind, here's a working example:</p>
  
  <pre><code>craft()-&gt;on('assets.saveAsset', function (Event $event) {
  
      if ($event-&gt;params['isNewAsset']) {
  
          $asset = $event-&gt;params['asset'];
  
          // Set the filename to a variable, appending the file extension
          $filename = 'filename-'.md5(time()).'.'.$asset-&gt;getExtension();
  
          // Rename the file on the server
          craft()-&gt;assets-&gt;renameFile($asset, $filename);
  
          // Set filename attribute and re-save asset
          $asset-&gt;setAttribute('filename', $filename);
          craft()-&gt;assets-&gt;storeFile($asset);
  
      }
  });
  </code></pre>
  
  <p>Note that in the above example, I'm hashing the current timestamp and adding it to the filename as an easy fix to ensure that it's unique. I don't know how you want your filenames to look or if duplicate filenames would even be an issue in your case, but you could of course implement a solution that tests for duplicate filenames and/or generates unique filenames in a different manner.</p>
  
  <p>To be honest, although the above should work I do feel this solution is a bit convoluted and I wouldn't be surprised if there's a better way – if there is, hopefully you'll have another answer.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-01-11T09:30:33.667Z
Answers.Text: Thanks for your answer and pointing the link to the docs. Unfortunately, although this code is non blocking anymore, it doesn't change the filename. Also what if I wanted to display the content of  $asset, what would be the best way to do this with php ?
Answers.UserDisplayName: Benj
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-01-11T09:48:55.160Z
Answers.Text: So this is extremely odd – I did some more testing w/ the above, and for some reason, it appears to work _sometimes_ – i.e. for certain files, not all. No idea why, but I'll do some more digging and update the answer if I can figure it out.
Answers.UserDisplayName: Mats Mikkel Rummelhoff
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-01-11T11:29:48.163Z
Answers.Text: @Benj Phew, this turned out to be a lot more complex than I first thought – just updated my answer with a solution that actually works. Hopefully it helps you out.
Answers.UserDisplayName: Mats Mikkel Rummelhoff
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-01-11T11:46:28.813Z
Answers.Text: Also, if you want to dump the contents of `$asset`, you could do it like this (inside the event listener): `var_dump($asset); die();`. That'll kill your script, but you should be able to see the dumped contents in your browser's dev tools (see http://cly.mmikkel.no/013Z1u1p102J for an example). Another option is to serialize the object and log it, e.g. `MyPluginHandlePlugin::log(serialize($asset));`, which would save the contents of `$asset` to `/craft/storage/runtime/logs/mypluginhandle.log`.
Answers.UserDisplayName: Mats Mikkel Rummelhoff
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-01-11T13:24:31.207Z
Answers.Text: Mats, thanks for the great answer. It now works indeed. Maybe there is another way, but at least this one works fine.
Answers.UserDisplayName: Benj
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-01-11T08:17:52.900Z
Answers.LastActivityDate: 2016-01-11T13:25:07.417Z
Answers.LastEditDate: 2016-01-11T13:25:07.417Z
Answers.UserDisplayName: Mats Mikkel Rummelhoff
Body: <pre><code>public function init()
  {
      craft()-&gt;on('assets.onBeforeSaveAsset', function(Event $event) {
          $asset = $event-&gt;params['asset'];
          $asset-&gt;setAttribute('filename', 'new name');
          craft()-&gt;assets-&gt;storeFile($asset);
      }
      );
  }
  </code></pre>
  
  <p>Here is the code I use in the primary plugin class. This is just a test as i'm learning. I know it should better be in service.
  This is supposed to change the filename upon uploading.</p>
  
  <p>Anyway this does nothing, when I upload an asset in the cp, the dialog with progress bars pops up but get stuck.
  How should I modify this for it to work ?</p>
  
Tags: <plugin-development><assets>
Title: Change asset name on upload
ThreadText: # Change asset name on upload
  
  (Asked by: username_0 on 2016-01-10)
  
  ```
  public function init()
  {
      craft()->on('assets.onBeforeSaveAsset', function(Event $event) {
          $asset = $event->params['asset'];
          $asset->setAttribute('filename', 'new name');
          craft()->assets->storeFile($asset);
      }
      );
  }
  
  ```
  
  Here is the code I use in the primary plugin class. This is just a test as i'm learning. I know it should better be in service.
  This is supposed to change the filename upon uploading.
  
  Anyway this does nothing, when I upload an asset in the cp, the dialog with progress bars pops up but get stuck.
  How should I modify this for it to work ?
  
  **Tags:** plugin-development, assets
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2016-01-11. Score: 6 | Accepted answer
  
  First, when you [attach event listeners](https://craftcms.com/docs/plugins/hooks-and-events#listening-for-events) using `craft.on`, the naming convention for the event name is `assets.beforeSaveEntry`, not `assets.onBeforeSaveEntry` (i.e., skip the `on` part). Both names appear to work, but the former is the one used in the docs and I'd recommend using that.
  
  Second, the reason why your upload "gets stuck" is your call to `craft()->assets->storeFile` inside the event listener. Basically, that call results in a loop, because `craft->assets->storeFile()` will fire another `beforeSaveAsset` event – making your script execute continually before timing out.
  
  As for actually changing the filename on upload; unfortunately, if there's a reliable way to change the asset filename *before the asset is saved*, I haven't been able to find it.
  
  However, if you can work with the `assets.saveAsset` event (which is fired after the asset is uploaded and saved on the server), I found a way:
  
  First, set up an event listener for `assets.saveAsset`. Inside the event listener, you need to check the `$event` object's `isNewAsset` property; making sure the filename is only changed the first time the asset is saved and preventing the loop mentioned above.
  
  Concerning the actual filename, there's a couple of issues to consider. For one, the filename needs to be unique (to that particular folder, as least). If you attempt to store an asset with an existing filename, Craft will use the original filename for your upload (I'd expect Craft to either ask if you wanted to replace the existing file, or suffix the filename with a number, but that doesn't appear to be the case). Secondly, the filename needs to include the file's extension (i.e. `jpg` or `pdf`). And finally; because this code runs *after* the asset has been saved and the file is already stored on the server, it isn't enough to set the filename attribute to the AssetFileModel object (i.e. `$asset`), you'll also need to rename the actual file.
  
  Keeping these issues in mind, here's a working example:
  
  ```
  craft()->on('assets.saveAsset', function (Event $event) {
  
      if ($event->params['isNewAsset']) {
  
          $asset = $event->params['asset'];
  
          // Set the filename to a variable, appending the file extension
          $filename = 'filename-'.md5(time()).'.'.$asset->getExtension();
  
          // Rename the file on the server
          craft()->assets->renameFile($asset, $filename);
  
          // Set filename attribute and re-save asset
          $asset->setAttribute('filename', $filename);
          craft()->assets->storeFile($asset);
  
      }
  });
  
  ```
  
  Note that in the above example, I'm hashing the current timestamp and adding it to the filename as an easy fix to ensure that it's unique. I don't know how you want your filenames to look or if duplicate filenames would even be an issue in your case, but you could of course implement a solution that tests for duplicate filenames and/or generates unique filenames in a different manner.
  
  To be honest, although the above should work I do feel this solution is a bit convoluted and I wouldn't be surprised if there's a better way – if there is, hopefully you'll have another answer.
  
  > **Comments:**
  > **username_0**: Thanks for your answer and pointing the link to the docs. Unfortunately, although this code is non blocking anymore, it doesn't change the filename. Also what if I wanted to display the content of  $asset, what would be the best way to do this with php ?  
  > **username_1**: So this is extremely odd – I did some more testing w/ the above, and for some reason, it appears to work _sometimes_ – i.e. for certain files, not all. No idea why, but I'll do some more digging and update the answer if I can figure it out.  
  > **username_1**: @username_0 Phew, this turned out to be a lot more complex than I first thought – just updated my answer with a solution that actually works. Hopefully it helps you out.  
  > **username_1**: Also, if you want to dump the contents of `$asset`, you could do it like this (inside the event listener): `var_dump($asset); die();`. That'll kill your script, but you should be able to see the dumped contents in your browser's dev tools (see http://cly.mmikkel.no/013Z1u1p102J for an example). Another option is to serialize the object and log it, e.g. `MyPluginHandlePlugin::log(serialize($asset));`, which would save the contents of `$asset` to `/craft/storage/runtime/logs/mypluginhandle.log`.  
  > **username_0**: username_1, thanks for the great answer. It now works indeed. Maybe there is another way, but at least this one works fine.  
  
  ---
  
  