<p>Craft's developer support helped me out with this.</p>
<p>The key was to use <code>Asset::EVENT_AFTER_SAVE</code> and the Craft asset service's <a href="https://docs.craftcms.com/api/v4/craft-services-assets.html#public-methods" rel="nofollow noreferrer">moveAsset</a> function.</p>
<pre class="lang-php prettyprint-override"><code>use yii\base\Event;
use craft\elements\Asset;
use craft\events\ModelEvent

class SiteModule extends \yii\base\Module
{

    public function init()
    {
        // ...

        $this-&gt;registerAssetEvents();
    }

    private function registerAssetEvents()
    {
        // Automatically assign asset volumes on upload, based on file kind.
        Event::on(
            Asset::class,
            Asset::EVENT_AFTER_SAVE,
            function (ModelEvent $event) {
                $asset = $event-&gt;sender;

                // mp4s which are not being put into the videos volume (id 2)
                // will be moved to the videos volume
                // NB this requires a GeneralConfig::$extraFileKinds definition for mp4s.
                if ($asset-&gt;kind == 'mp4' &amp;&amp; $asset-&gt;getVolumeId() !== 2) {
                    $targetFolder = Craft::$app-&gt;assets-&gt;getRootFolderByVolumeId(2);
                    Craft::$app-&gt;assets-&gt;moveAsset($asset, $targetFolder);
                }
            }
        );
    }
}
</code></pre>

CC BY-SA 4.0
2022-12-13T13:19:05.197Z
2022-12-13T13:19:05.197Z
Josh Harrison
<p>I'm trying to set the asset volume dynamically for new assets, using a module. I would like the volume to be based on the asset's file kind – in my case, automatically putting MP4s into a 'Videos' asset volume.</p>
<p>I would like this to work when the asset is uploaded via an assets field, or directly via the Assets CP screen.</p>
<p>The Craft docs for this stuff are a bit of a mystery to me as they lack examples and explanations... here's what I've tried so far in my site module. It works when uploading assets on the Assets CP screen, but it does nothing when uploading via an Assets field on an entry:</p>
<pre class="lang-php prettyprint-override"><code>use yii\base\Event;
use craft\elements\Asset;
use craft\events\ModelEvent;

// Automatically put MP4 uploads into the 'Videos' asset volume (volume ID 2, folder ID 2).
// This function is called in the module's constructor.
private function registerDynamicAssetVolumeSettings()
{
    Event::on(
        Asset::class,
        Asset::EVENT_BEFORE_SAVE,
        function (ModelEvent $event) {

            // only act on new assets matching my `mp4` custom file kind
            if ($event-&gt;isNew &amp;&amp; $event-&gt;sender-&gt;kind == 'mp4') {

                // only act on mp4s which are not already being put into the mp4 volume
                if ($event-&gt;sender-&gt;getVolumeId() !== 2) {
                    $event-&gt;sender-&gt;setVolumeId(2);
                    $event-&gt;sender-&gt;newLocation = '{folder:2}' . $event-&gt;sender-&gt;getFilename();
                }
            }
        }
    );
}
</code></pre>
<p>Thanks in advance for any thoughts </p>

<assets><php><modules><craft4><volumes>
Set asset volume dynamically via module depending on uploaded file kind
# Set asset volume dynamically via module depending on uploaded file kind

(Asked by: username_0 on 2022-11-17)

I'm trying to set the asset volume dynamically for new assets, using a module. I would like the volume to be based on the asset's file kind – in my case, automatically putting MP4s into a 'Videos' asset volume.
I would like this to work when the asset is uploaded via an assets field, or directly via the Assets CP screen.
The Craft docs for this stuff are a bit of a mystery to me as they lack examples and explanations... here's what I've tried so far in my site module. It works when uploading assets on the Assets CP screen, but it does nothing when uploading via an Assets field on an entry:
use yii\base\Event;
use craft\elements\Asset;
use craft\events\ModelEvent;

// Automatically put MP4 uploads into the 'Videos' asset volume (volume ID 2, folder ID 2).
// This function is called in the module's constructor.
private function registerDynamicAssetVolumeSettings()
{
    Event::on(
        Asset::class,
        Asset::EVENT_BEFORE_SAVE,
        function (ModelEvent $event) {

            // only act on new assets matching my `mp4` custom file kind
            if ($event->isNew && $event->sender->kind == 'mp4') {

                // only act on mp4s which are not already being put into the mp4 volume
                if ($event->sender->getVolumeId() !== 2) {
                    $event->sender->setVolumeId(2);
                    $event->sender->newLocation = '{folder:2}' . $event->sender->getFilename();
                }
            }
        }
    );
}

Thanks in advance for any thoughts

**Tags:** assets, php, modules, craft4, volumes

---

## 1 answers

### Answer by username_0 on 2022-12-13. Score: 1 | Accepted answer

Craft's developer support helped me out with this.
The key was to use Asset::EVENT_AFTER_SAVE and the Craft asset service's moveAsset function.
use yii\base\Event;
use craft\elements\Asset;
use craft\events\ModelEvent

class SiteModule extends \yii\base\Module
{

    public function init()
    {
        // ...

        $this->registerAssetEvents();
    }

    private function registerAssetEvents()
    {
        // Automatically assign asset volumes on upload, based on file kind.
        Event::on(
            Asset::class,
            Asset::EVENT_AFTER_SAVE,
            function (ModelEvent $event) {
                $asset = $event->sender;

                // mp4s which are not being put into the videos volume (id 2)
                // will be moved to the videos volume
                // NB this requires a GeneralConfig::$extraFileKinds definition for mp4s.
                if ($asset->kind == 'mp4' && $asset->getVolumeId() !== 2) {
                    $targetFolder = Craft::$app->assets->getRootFolderByVolumeId(2);
                    Craft::$app->assets->moveAsset($asset, $targetFolder);
                }
            }
        );
    }
}


---

