Body: <h1>Preamble</h1>
  
  <ul>
  <li>Craft 3.1.26</li>
  <li>PHP 7.2.8 on Mamp Pro 5.1.1</li>
  </ul>
  
  <p>I browsed to my <code>storage/reports</code> folder and made sure in Finder than full read/write privileges are granted.</p>
  
  <h1>What's goin on</h1>
  
  <p>I have a module with a service that has two methods currently:</p>
  
  <ul>
  <li><code>generateScriptPdf()</code>: gets information from a given entry and generates a PDF with its data,</li>
  <li><code>savePdfAsAsset()</code>: called by the former and takes some data about that PDF file and uses it to create a new Asset.</li>
  </ul>
  
  <p><code>generateScriptPdf()</code> is working fine and it saves the PDF in <code>storage/reports</code>.</p>
  
  <p><code>savePdfAsAsset()</code>, however, responds with a 500 status and this error message:</p>
  
  <pre><code>PHP Warning 'yii\base\ErrorException' with message 'unlink(/Users/steven/Code/vetscripts/storage/reports/): Operation not permitted' 
  </code></pre>
  
  <h1>My real question</h1>
  
  <p>This is my first time trying to generate a file and then save/upload that file as a Craft Asset, so I'm sure I'm doing something a little off and I know that right now my code is not very defensive. <strong>Are there any important parts or steps I am missing when trying to save my file as an Asset?</strong></p>
  
  <h1>Service</h1>
  
  <pre class="lang-php prettyprint-override"><code>&lt;?php
  namespace modules\vetscripts\services;
  
  use Craft;
  use craft\elements\Asset;
  use craft\elements\Entry;
  use craft\base\Component;
  use Fpdf\Fpdf;
  
  class Scripts extends Component
  {
      /**
       * Generate Script PDF
       *
       * @param $scriptId
       * @return array
       */
      public function generateScriptPdf($scriptId)
      {
          $script = Entry::find()
              -&gt;section('scripts')
              -&gt;id($scriptId)
              -&gt;one();
  
          $pdf = new Fpdf('P','in','Letter');
          $pdf-&gt;SetFont('Times');
          $pdf-&gt;AddPage();
          $pdf-&gt;Cell(40,10,$script-&gt;title);
  
          $filepath = CRAFT_BASE_PATH . '/storage/reports/';
          if (!file_exists($filepath)) {
              mkdir($filepath, 0777, true);
          }
          $filename = "Script_Report_$script-&gt;title.pdf";
  
          $success = $pdf-&gt;Output('F', $filepath.$filename, false);
          if (!$success) {
              Craft::error("Could not save the report $filepath.$filename", __METHOD__);
          }
  
          $this-&gt;savePdfAsAsset($filepath, $filename, 7, 3);
  
          return [
              'success' =&gt; true
          ];
      }
  
      public function savePdfAsAsset($tempPath, $filename, $folderId, $volumeId)
      {
          $asset = new Asset();
          $asset-&gt;tempFilePath = $tempPath;
          $asset-&gt;filename = $filename;
          $asset-&gt;newFolderId = $folderId;
          $asset-&gt;volumeId = $volumeId;
          $asset-&gt;avoidFilenameConflicts = true;
          $asset-&gt;setScenario(Asset::SCENARIO_CREATE);
  
          $result = Craft::$app-&gt;getElements()-&gt;saveElement($asset);
  
          if (!$result) {
              return ['message' =&gt; 'Error'];
          }
  
          return ['success' =&gt; true];
      }
  }
  </code></pre>
  
  <h1>Stack trace</h1>
  
  <pre><code>#0 /Users/steven/Code/vetscripts/vendor/yiisoft/yii2/helpers/BaseFileHelper.php(407): ::unlink('???')
  #1 /Users/steven/Code/vetscripts/vendor/craftcms/cms/src/elements/Asset.php(1516): yii\helpers\BaseFileHelper::unlink('???')
  #2 /Users/steven/Code/vetscripts/vendor/craftcms/cms/src/elements/Asset.php(1275): craft\elements\Asset-&gt;_relocateFile()
  #3 /Users/steven/Code/vetscripts/vendor/craftcms/cms/src/services/Elements.php(515): craft\elements\Asset-&gt;afterSave('???')
  #4 /Users/steven/Code/vetscripts/modules/craft-vetscripts/src/services/Scripts.php(82): craft\services\Elements-&gt;saveElement('???', '???', '???')
  #5 /Users/steven/Code/vetscripts/modules/craft-vetscripts/src/services/Scripts.php(65): modules\vetscripts\services\Scripts-&gt;savePdfAsAsset('???', '???', '???', '???')
  #6 /Users/steven/Code/vetscripts/modules/craft-vetscripts/src/controllers/ScriptsController.php(46): modules\vetscripts\services\Scripts-&gt;generateScriptPdf('???')
  #7 /Users/steven/Code/vetscripts/vendor/yiisoft/yii2/base/InlineAction.php(57): modules\vetscripts\controllers\ScriptsController-&gt;actionPdf()
  #8 /Users/steven/Code/vetscripts/vendor/yiisoft/yii2/base/InlineAction.php(57): ::call_user_func_array:{/Users/steven/Code/vetscripts/vendor/yiisoft/yii2/base/InlineAction.php:57}('???', '???')
  #9 /Users/steven/Code/vetscripts/vendor/yiisoft/yii2/base/Controller.php(157): yii\base\InlineAction-&gt;runWithParams('???')
  #10 /Users/steven/Code/vetscripts/vendor/craftcms/cms/src/web/Controller.php(109): modules\vetscripts\controllers\ScriptsController-&gt;runAction('???', '???')
  #11 /Users/steven/Code/vetscripts/vendor/yiisoft/yii2/base/Module.php(528): modules\vetscripts\controllers\ScriptsController-&gt;runAction('???', '???')
  #12 /Users/steven/Code/vetscripts/vendor/craftcms/cms/src/web/Application.php(297): craft\web\Application-&gt;runAction('???', '???')
  #13 /Users/steven/Code/vetscripts/vendor/craftcms/cms/src/web/Application.php(565): craft\web\Application-&gt;runAction('???', '???')
  #14 /Users/steven/Code/vetscripts/vendor/craftcms/cms/src/web/Application.php(281): craft\web\Application-&gt;_processActionRequest('???')
  #15 /Users/steven/Code/vetscripts/vendor/yiisoft/yii2/base/Application.php(386): craft\web\Application-&gt;handleRequest('???')
  #16 /Users/steven/Code/vetscripts/web/index.php(21): craft\web\Application-&gt;run()
  #17 {main}
  </code></pre>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-05-20T12:53:58.417Z
Comments.Text: Your sending the folder path without the filename to the `savePdfAsAsset` method. If you add the filename to the path, your example should work.
Comments.UserDisplayName: Fred Carlsen
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-05-20T15:24:23.563Z
Comments.Text: Awesome, it works now! However two copies of the pdf are saved as an asset with one of them having a datetime stamp appended to the filename, e.g. `Script_Report_8804_190520_152057.pdf`. Any idea why that might be happening? In any case, post an answer and I'll mark it as accepted. Thanks!
Comments.UserDisplayName: Steven Thate
Tags: <plugin-development><assets><modules><pdf><files>
Title: How do I correctly upload a new Asset from a temp file I generated from a service method?
ThreadText: # How do I correctly upload a new Asset from a temp file I generated from a service method?
  
  (Asked by: username_0 on 2019-05-19)
  
  # Preamble
  
  * Craft 3.1.26
  * PHP 7.2.8 on Mamp Pro 5.1.1
  
  I browsed to my `storage/reports` folder and made sure in Finder than full read/write privileges are granted.
  
  # What's goin on
  
  I have a module with a service that has two methods currently:
  
  * `generateScriptPdf()`: gets information from a given entry and generates a PDF with its data,
  * `savePdfAsAsset()`: called by the former and takes some data about that PDF file and uses it to create a new Asset.
  
  `generateScriptPdf()` is working fine and it saves the PDF in `storage/reports`.
  
  `savePdfAsAsset()`, however, responds with a 500 status and this error message:
  
  ```
  PHP Warning 'yii\base\ErrorException' with message 'unlink(/Users/username_0/Code/vetscripts/storage/reports/): Operation not permitted' 
  
  ```
  
  # My real question
  
  This is my first time trying to generate a file and then save/upload that file as a Craft Asset, so I'm sure I'm doing something a little off and I know that right now my code is not very defensive. **Are there any important parts or steps I am missing when trying to save my file as an Asset?**
  
  # Service
  
  ```php
  <?php
  namespace modules\vetscripts\services;
  
  use Craft;
  use craft\elements\Asset;
  use craft\elements\Entry;
  use craft\base\Component;
  use Fpdf\Fpdf;
  
  class Scripts extends Component
  {
      /**
       * Generate Script PDF
       *
       * @param $scriptId
       * @return array
       */
      public function generateScriptPdf($scriptId)
      {
          $script = Entry::find()
              ->section('scripts')
              ->id($scriptId)
              ->one();
  
          $pdf = new Fpdf('P','in','Letter');
          $pdf->SetFont('Times');
          $pdf->AddPage();
          $pdf->Cell(40,10,$script->title);
  
          $filepath = CRAFT_BASE_PATH . '/storage/reports/';
          if (!file_exists($filepath)) {
              mkdir($filepath, 0777, true);
          }
          $filename = "Script_Report_$script->title.pdf";
  
          $success = $pdf->Output('F', $filepath.$filename, false);
          if (!$success) {
              Craft::error("Could not save the report $filepath.$filename", __METHOD__);
          }
  
          $this->savePdfAsAsset($filepath, $filename, 7, 3);
  
          return [
              'success' => true
          ];
      }
  
      public function savePdfAsAsset($tempPath, $filename, $folderId, $volumeId)
      {
          $asset = new Asset();
          $asset->tempFilePath = $tempPath;
          $asset->filename = $filename;
          $asset->newFolderId = $folderId;
          $asset->volumeId = $volumeId;
          $asset->avoidFilenameConflicts = true;
          $asset->setScenario(Asset::SCENARIO_CREATE);
  
          $result = Craft::$app->getElements()->saveElement($asset);
  
          if (!$result) {
              return ['message' => 'Error'];
          }
  
          return ['success' => true];
      }
  }
  
  ```
  
  # Stack trace
  
  ```
  #0 /Users/username_0/Code/vetscripts/vendor/yiisoft/yii2/helpers/BaseFileHelper.php(407): ::unlink('???')
  #1 /Users/username_0/Code/vetscripts/vendor/craftcms/cms/src/elements/Asset.php(1516): yii\helpers\BaseFileHelper::unlink('???')
  #2 /Users/username_0/Code/vetscripts/vendor/craftcms/cms/src/elements/Asset.php(1275): craft\elements\Asset->_relocateFile()
  #3 /Users/username_0/Code/vetscripts/vendor/craftcms/cms/src/services/Elements.php(515): craft\elements\Asset->afterSave('???')
  #4 /Users/username_0/Code/vetscripts/modules/craft-vetscripts/src/services/Scripts.php(82): craft\services\Elements->saveElement('???', '???', '???')
  #5 /Users/username_0/Code/vetscripts/modules/craft-vetscripts/src/services/Scripts.php(65): modules\vetscripts\services\Scripts->savePdfAsAsset('???', '???', '???', '???')
  #6 /Users/username_0/Code/vetscripts/modules/craft-vetscripts/src/controllers/ScriptsController.php(46): modules\vetscripts\services\Scripts->generateScriptPdf('???')
  #7 /Users/username_0/Code/vetscripts/vendor/yiisoft/yii2/base/InlineAction.php(57): modules\vetscripts\controllers\ScriptsController->actionPdf()
  #8 /Users/username_0/Code/vetscripts/vendor/yiisoft/yii2/base/InlineAction.php(57): ::call_user_func_array:{/Users/username_0/Code/vetscripts/vendor/yiisoft/yii2/base/InlineAction.php:57}('???', '???')
  #9 /Users/username_0/Code/vetscripts/vendor/yiisoft/yii2/base/Controller.php(157): yii\base\InlineAction->runWithParams('???')
  #10 /Users/username_0/Code/vetscripts/vendor/craftcms/cms/src/web/Controller.php(109): modules\vetscripts\controllers\ScriptsController->runAction('???', '???')
  #11 /Users/username_0/Code/vetscripts/vendor/yiisoft/yii2/base/Module.php(528): modules\vetscripts\controllers\ScriptsController->runAction('???', '???')
  #12 /Users/username_0/Code/vetscripts/vendor/craftcms/cms/src/web/Application.php(297): craft\web\Application->runAction('???', '???')
  #13 /Users/username_0/Code/vetscripts/vendor/craftcms/cms/src/web/Application.php(565): craft\web\Application->runAction('???', '???')
  #14 /Users/username_0/Code/vetscripts/vendor/craftcms/cms/src/web/Application.php(281): craft\web\Application->_processActionRequest('???')
  #15 /Users/username_0/Code/vetscripts/vendor/yiisoft/yii2/base/Application.php(386): craft\web\Application->handleRequest('???')
  #16 /Users/username_0/Code/vetscripts/web/index.php(21): craft\web\Application->run()
  #17 {main}
  
  ```
  
  **Tags:** plugin-development, assets, modules, pdf, files
  
  > **Comments:**
  > **username_1**: Your sending the folder path without the filename to the `savePdfAsAsset` method. If you add the filename to the path, your example should work.  
  > **username_0**: Awesome, it works now! However two copies of the pdf are saved as an asset with one of them having a datetime stamp appended to the filename, e.g. `Script_Report_8804_190520_152057.pdf`. Any idea why that might be happening? In any case, post an answer and I'll mark it as accepted. Thanks!  
  
  ---
  
  ## 0 answers
  
  