Answers.Body: <p>You need to create a <a href="https://craftcms.com/docs/3.x/extend/controllers.html" rel="nofollow noreferrer">Controller</a> to handle the server-side saving of the image. The Controller should roughly perform the following steps:</p>
  <ol>
  <li>Receive and validate a POST request with the base64-encoded image as the request body.</li>
  <li>Convert the base64 back to binary (you can use the <a href="https://www.php.net/manual/en/function.base64-decode.php" rel="nofollow noreferrer">base64_decode</a> function) and store it on disk in a temporary location.</li>
  <li>Create the subfolder to store the image in (the action method should also accept the ID of the original video so that it can find the video asset and put the screenshots in the right folder).</li>
  <li>Programmatically create an Asset. Check out the example code given in the documentation for <a href="https://docs.craftcms.com/api/v3/craft-services-elements.html#method-saveelement" rel="nofollow noreferrer">craft\services\Elements::saveElement</a>. Assets work similar, only you're creating an <code>craft\elements\Asset</code> object instead of an <code>Entry</code>. I'll include some sample code to get you started below.</li>
  <li>Save the asset (it's moved to the appropriate folder automatically if you use the sample code below). Respond to the request with the ID of the newly created asset, or with error messages in case something goes wrong.</li>
  </ol>
  <p>Beyond that, make sure to check the documentation on Controllers linked above regarding the following topics:</p>
  <ul>
  <li>Access control.</li>
  <li>Parameter / POST body handling (the endpoint should only allow POST requests).</li>
  <li>Validation (validate the base64-encoded image and any additional parameters like the asset ID of the video).</li>
  </ul>
  <p>Once the Controller with that endpoint is in place, you can post to it from your JavaScript code once you want to save the screenshot using <code>fetch()</code>.</p>
  <h3>Create an asset programmatically</h3>
  <p>Just some sample code for creating an asset to get you started:</p>
  <pre class="lang-php prettyprint-override"><code>&lt;?php
  
  use craft\elements\Asset;
  
  $tmpPath = Craft::$app-&gt;getPath()-&gt;getTempPath() . '/tmp-screenshots/';
  
  // generate this file from the post body using base64_decode and file_put_contents
  $tmpFile = $tmpPath . 'decoded-image-file.jpg';
  
  // create a new asset
  $asset = new Asset();
  $asset-&gt;tempFilePath = $tmpFile;
  $asset-&gt;filename = 'screenshot-xy.jpg';
  $asset-&gt;title = 'Screenshot XY';
  $asset-&gt;avoidFilenameConflicts = true;
  $asset-&gt;setScenario(Asset::SCENARIO_CREATE);
  
  // you can determine $volume and $folder using the ID of the video asset
  $asset-&gt;newFolderId = $folder-&gt;id;
  $asset-&gt;volumeId = $volume-&gt;id;
  $asset-&gt;uploaderId = $author-&gt;id;
  
  // save the asset
  $success = Craft::$app-&gt;getElements()-&gt;saveElement($asset);
  if (!$success) {
      // respond with errors ($asset-&gt;getErrors())
  }
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-11-24T15:26:58.253Z
Answers.Text: thank you very much for your detailed answer. I will try to get it work the next days.
Answers.UserDisplayName: Crazy Haps
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-11-24T09:44:00.103Z
Answers.LastActivityDate: 2021-11-24T09:44:00.103Z
Answers.UserDisplayName: MoritzLost
Body: <p>I started coding a custom plugin, it takes a video file from the asset and showing the file in a video-player (CP). The user is now able to take screenshots of the video (using JS) by clicking a button. The JS code exports a base64-encoded image.</p>
  <p>I managed it to get the video file into the plugin, but I have no clue how to save these screenshots in an asset (subfolder of the video).</p>
  <p>I'm not really familiar with php, that's why I stuck here.</p>
  <p>Is it even possible to save base64 images?</p>
  <p>Looking for help, many thanks in advance.
  And thank you guys for all the work here on this page,
  it already helped my a lot.</p>
  <p>BTW: If anyone is interested in helping me out with a proper coded custom plugin,
  let me know, it`s payed. ;-)</p>
  <p><a href="https://i.sstatic.net/wyfij.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/wyfij.jpg" alt="" /></a></p>
  
Tags: <plugin-development><video>
Title: upload base64 image -> save in assets -> custom plugin
ThreadText: # upload base64 image -> save in assets -> custom plugin
  
  (Asked by: username_0 on 2021-11-24)
  
  I started coding a custom plugin, it takes a video file from the asset and showing the file in a video-player (CP). The user is now able to take screenshots of the video (using JS) by clicking a button. The JS code exports a base64-encoded image.
  
  I managed it to get the video file into the plugin, but I have no clue how to save these screenshots in an asset (subfolder of the video).
  
  I'm not really familiar with php, that's why I stuck here.
  
  Is it even possible to save base64 images?
  
  Looking for help, many thanks in advance.
  And thank you guys for all the work here on this page,
  it already helped my a lot.
  
  BTW: If anyone is interested in helping me out with a proper coded custom plugin,
  let me know, it`s payed. ;-)
  
  [![](https://i.sstatic.net/wyfij.jpg)](https://i.sstatic.net/wyfij.jpg)
  
  **Tags:** plugin-development, video
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2021-11-24. Score: 3
  
  You need to create a [Controller](https://craftcms.com/docs/3.x/extend/controllers.html) to handle the server-side saving of the image. The Controller should roughly perform the following steps:
  
  1. Receive and validate a POST request with the base64-encoded image as the request body.
  2. Convert the base64 back to binary (you can use the [base64\_decode](https://www.php.net/manual/en/function.base64-decode.php) function) and store it on disk in a temporary location.
  3. Create the subfolder to store the image in (the action method should also accept the ID of the original video so that it can find the video asset and put the screenshots in the right folder).
  4. Programmatically create an Asset. Check out the example code given in the documentation for [craft\services\Elements::saveElement](https://docs.craftcms.com/api/v3/craft-services-elements.html#method-saveelement). Assets work similar, only you're creating an `craft\elements\Asset` object instead of an `Entry`. I'll include some sample code to get you started below.
  5. Save the asset (it's moved to the appropriate folder automatically if you use the sample code below). Respond to the request with the ID of the newly created asset, or with error messages in case something goes wrong.
  
  Beyond that, make sure to check the documentation on Controllers linked above regarding the following topics:
  
  * Access control.
  * Parameter / POST body handling (the endpoint should only allow POST requests).
  * Validation (validate the base64-encoded image and any additional parameters like the asset ID of the video).
  
  Once the Controller with that endpoint is in place, you can post to it from your JavaScript code once you want to save the screenshot using `fetch()`.
  
  ### Create an asset programmatically
  
  Just some sample code for creating an asset to get you started:
  
  ```php
  <?php
  
  use craft\elements\Asset;
  
  $tmpPath = Craft::$app->getPath()->getTempPath() . '/tmp-screenshots/';
  
  // generate this file from the post body using base64_decode and file_put_contents
  $tmpFile = $tmpPath . 'decoded-image-file.jpg';
  
  // create a new asset
  $asset = new Asset();
  $asset->tempFilePath = $tmpFile;
  $asset->filename = 'screenshot-xy.jpg';
  $asset->title = 'Screenshot XY';
  $asset->avoidFilenameConflicts = true;
  $asset->setScenario(Asset::SCENARIO_CREATE);
  
  // you can determine $volume and $folder using the ID of the video asset
  $asset->newFolderId = $folder->id;
  $asset->volumeId = $volume->id;
  $asset->uploaderId = $author->id;
  
  // save the asset
  $success = Craft::$app->getElements()->saveElement($asset);
  if (!$success) {
      // respond with errors ($asset->getErrors())
  }
  
  ```
  
  > **Comments:**
  > **username_0**: thank you very much for your detailed answer. I will try to get it work the next days.  
  
  ---
  
  