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);


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.

1 Answer 1


There might be a way to do this with CBaseController::renderFile(), but I'd just use craft()->request->sendFile().

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.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.