Answers.Body: <p>There might be a way to do this with <code>CBaseController::renderFile()</code>, but I'd just use <a href="https://craftcms.com/classreference/services/HttpRequestService#sendFile-detail" rel="nofollow"><code>craft()-&gt;request-&gt;sendFile()</code></a>.</p>
  
  <p>The 3rd parameter is an optional <code>$options</code> array and you can pass a <code>'forceDownload' =&gt; true</code> as one of the key => value pairs to force it to download to the browser.</p>
  
  <p>Instead of hardcoding the the path to your public assets folder, you can do something like:</p>
  
  <pre><code>$path = IOHelper::getFolderName(craft()-&gt;request-&gt;getScriptFile());
  </code></pre>
  
  <p>That should get you the path to the folder your public <code>index.php</code> file is executing in and you can tack on your public asset path from there.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-05-11T02:23:19.483Z
Answers.LastActivityDate: 2016-05-11T02:23:19.483Z
Answers.UserDisplayName: Brad Bell
Body: <p>I have a controller which fetches an asset from an entry (this is the service method that provides the asset):</p>
  
  <pre><code>public function findPoster($entryId) {
      $criteria = craft()-&gt;elements-&gt;getCriteria(ElementType::Entry);
      $criteria-&gt;id = $entryId;
  
      $entry = $criteria-&gt;first();
  
      if ($entry) {
          if ($entry-&gt;downloadItem) {
              return $entry-&gt;downloadItem-&gt;first();
          }
      }
  
      return null;
  }
  </code></pre>
  
  <p>That works great, however now I need to send the asset to the browser. Having a little poke around in the method listing I see there is a <code>CBaseController::renderFile()</code> which sounds to be what I need, however I can't work out the correct way to build a path to the file. Accessing <code>$url</code> from the asset I've fetched returns a public relative path but obviously I need the path on the filesystem.</p>
  
  <hr>
  
  <p>So far I've got this working:</p>
  
  <pre><code>$name = strtolower($asset-&gt;title) . '.' . $asset-&gt;extension;
  
  header('Content-Type: ' . $asset-&gt;getMimeType());
  header('Content-Disposition: attachment; filename=' . $name);
  
  $path = realpath(craft()-&gt;basePath . '/../../public/' . $asset-&gt;url);
  
  die(file_get_contents($path));
  </code></pre>
  
  <p>However this is far from ideal because:</p>
  
  <ul>
  <li>I have to hardcode the <code>public</code> directory which isn't the case at any other point in Craft, so it feels really dirty.</li>
  <li>Manually setting the headers seems like something a controller method would be able to take care of properly.</li>
  </ul>
  
Tags: <plugin-development><assets><controller><assetfilemodel>
Title: Send an asset from a plugin controller
ThreadText: # Send an asset from a plugin controller
  
  (Asked by: username_0 on 2016-05-11)
  
  I have a controller which fetches an asset from an entry (this is the service method that provides the asset):
  
  ```
  public function findPoster($entryId) {
      $criteria = craft()->elements->getCriteria(ElementType::Entry);
      $criteria->id = $entryId;
  
      $entry = $criteria->first();
  
      if ($entry) {
          if ($entry->downloadItem) {
              return $entry->downloadItem->first();
          }
      }
  
      return null;
  }
  
  ```
  
  That works great, however now I need to send the asset to the browser. Having a little poke around in the method listing I see there is a `CBaseController::renderFile()` which sounds to be what I need, however I can't work out the correct way to build a path to the file. Accessing `$url` from the asset I've fetched returns a public relative path but obviously I need the path on the filesystem.
  
  ---
  
  So far I've got this working:
  
  ```
  $name = strtolower($asset->title) . '.' . $asset->extension;
  
  header('Content-Type: ' . $asset->getMimeType());
  header('Content-Disposition: attachment; filename=' . $name);
  
  $path = realpath(craft()->basePath . '/../../public/' . $asset->url);
  
  die(file_get_contents($path));
  
  ```
  
  However this is far from ideal because:
  
  * I have to hardcode the `public` directory which isn't the case at any other point in Craft, so it feels really dirty.
  * Manually setting the headers seems like something a controller method would be able to take care of properly.
  
  **Tags:** plugin-development, assets, controller, assetfilemodel
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2016-05-11. Score: 2 | Accepted answer
  
  There might be a way to do this with `CBaseController::renderFile()`, but I'd just use [`craft()->request->sendFile()`](https://craftcms.com/classreference/services/HttpRequestService#sendFile-detail).
  
  The 3rd parameter is an optional `$options` array and you can pass a `'forceDownload' => true` as one of the key => value pairs to force it to download to the browser.
  
  Instead of hardcoding the the path to your public assets folder, you can do something like:
  
  ```
  $path = IOHelper::getFolderName(craft()->request->getScriptFile());
  
  ```
  
  That should get you the path to the folder your public `index.php` file is executing in and you can tack on your public asset path from there.
  
  
  ---
  
  