<p>I think you need to resave the element after using <code>setFieldValue</code>. Maybe try hooking into <code>EVENT_AFTER_SAVE</code> instead?</p>
<pre class="lang-php prettyprint-override"><code>Event::on(
    Asset::class,
    Asset::EVENT_AFTER_SAVE,
    function (AssetEvent $event) {
        $asset = $event-&gt;asset;
        //Avoid endless loop if the asset already has duration set
        if ($asset-&gt;extension == 'mp3' &amp;&amp; !$asset-&gt;duration) {
            $mp3 = new Mp3($asset-&gt;path);
            $duration = $mp3-&gt;getDuration();
            $asset-&gt;setFieldValue('duration', $duration);
            Craft::$app-&gt;getElements()-&gt;saveElement($asset);
        }
        
    }
);
</code></pre>

CC BY-SA 4.0
2024-01-25T20:52:43.790Z
Unfortunately that doesn't work. The asset is in S3, so I don't want to download it again. It has to happen before uploading it to S3. I am also getting the following errors: `Argument #1 ($event) must be of type craft\events\AssetEvent, craft\events\ModelEvent given` and `Invalid field handle: duration` (the duration field does exist though!) I did workaround those errors, and can see the duration is in the dirty fields array and the saveElement function is being called, but it's just not being saved!
thomasjonas
CC BY-SA 4.0
2024-03-27T20:50:18.163Z
@thomasjonas - Looking at the [EVENT_AFTER_SAVE docs](https://docs.craftcms.com/api/v4/craft-base-element.html#event-after-save), it's returning a `ModelEvent` instead of an `AssetEvent`. 

So changing...

`function (AssetEvent $event) {` 

...to ... 

`function (ModelEvent $event) {`

... should fix this error.
Dan Letsche
CC BY-SA 4.0
2024-01-25T18:54:23.300Z
2024-01-25T18:54:23.300Z
Dalton Rooney
<p>I'm trying to set the value of a custom field for an asset while uploading the asset. But somehow the value is not being saved. I can see the data in the <code>EVENT_BEFORE_SAVE</code> and <code>EVENT_AFTER_SAVE</code> hook, it is also in the dirty fields array, but it's just not saved in the database. What am I doing wrong?</p>
<pre><code>Event::on(
    Asset::class,
    Asset::EVENT_BEFORE_HANDLE_FILE,
    function (AssetEvent $event) {
        if (Craft::$app-&gt;getRequest()-&gt;getIsCpRequest()) {
            $asset = $event-&gt;asset;
            if ($asset-&gt;extension === 'mp3' &amp;&amp; $asset-&gt;tempFilePath) {
                $mp3 = new Mp3($asset-&gt;tempFilePath);
                $duration = $mp3-&gt;getDuration();
                $asset-&gt;setFieldValue('duration', $duration);
            }
        }
    }
);
</code></pre>

<assets><hook>
Saving metadata for asset when uploading file
# Saving metadata for asset when uploading file

(Asked by: username_0 on 2024-01-25)

I'm trying to set the value of a custom field for an asset while uploading the asset. But somehow the value is not being saved. I can see the data in the EVENT_BEFORE_SAVE and EVENT_AFTER_SAVE hook, it is also in the dirty fields array, but it's just not saved in the database. What am I doing wrong?
Event::on(
    Asset::class,
    Asset::EVENT_BEFORE_HANDLE_FILE,
    function (AssetEvent $event) {
        if (Craft::$app->getRequest()->getIsCpRequest()) {
            $asset = $event->asset;
            if ($asset->extension === 'mp3' && $asset->tempFilePath) {
                $mp3 = new Mp3($asset->tempFilePath);
                $duration = $mp3->getDuration();
                $asset->setFieldValue('duration', $duration);
            }
        }
    }
);

**Tags:** assets, hook


---

## 1 answers

### Answer by username_1 on 2024-01-25. Score: 1

I think you need to resave the element after using setFieldValue. Maybe try hooking into EVENT_AFTER_SAVE instead?
Event::on(
    Asset::class,
    Asset::EVENT_AFTER_SAVE,
    function (AssetEvent $event) {
        $asset = $event->asset;
        //Avoid endless loop if the asset already has duration set
        if ($asset->extension == 'mp3' && !$asset->duration) {
            $mp3 = new Mp3($asset->path);
            $duration = $mp3->getDuration();
            $asset->setFieldValue('duration', $duration);
            Craft::$app->getElements()->saveElement($asset);
        }
        
    }
);

> **Comments:**
> **username_0**: Unfortunately that doesn't work. The asset is in S3, so I don't want to download it again. It has to happen before uploading it to S3. I am also getting the following errors: `Argument #1 ($event) must be of type craft\events\AssetEvent, craft\events\ModelEvent given` and `Invalid field handle: duration` (the duration field does exist though!) I did workaround those errors, and can see the duration is in the dirty fields array and the saveElement function is being called, but it's just not being saved!  
> **username_2**: @username_0 - Looking at the [EVENT_AFTER_SAVE docs](https://docs.craftcms.com/api/v4/craft-base-element.html#event-after-save), it's returning a `ModelEvent` instead of an `AssetEvent`.   So changing...  `function (AssetEvent $event) {`   ...to ...   `function (ModelEvent $event) {`  ... should fix this error.  

---

