Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

General Questions

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

[solved] force file download


Go to End
Reply

10 Posts   2744 Views

Avatar
ekersten

17 February 2011 at 3:52am Community Member, 16 Posts

I have a controller method that is supposed to force-download an asset uploaded via backend. The method recieves the ID of such asset and uses SS_HTTPRequest.

The problem is that although i can directly access the asset in the template via $File.URL I can't read it via php because file_exists says $File.URL does not exists.

This is the method source

public function download(){

   $assetID = $this->request->param('ID');

   $do = DataObject::get_by_id('File', $assetID);
   
   if($do && file_exists($do->URL)){
    return SS_HTTPRequest::send_file(file_get_contents($do->URL), $do->Name);
   }else{
    echo 'error with ' . $do->URL . ' (' . file_exists($do->URL) . ')';
    return false;
   }

}

Am I missing something here?
Thanks in advance

Avatar
ekersten

17 February 2011 at 4:04am (Last edited: 17 February 2011 4:06am), Community Member, 16 Posts

After an our of trying i solved it with this piece of code

public function download(){

   $assetID = $this->request->param('ID');

   $do = DataObject::get_by_id('File', $assetID);
   
   if($do){
    return SS_HTTPRequest::send_file(file_get_contents(Director::absoluteBaseURL() . $do->Filename), $do->Name);
   }else{
    return false;
   }

}

Seems the combination "Director::absoluteBaseURL() . $do->Filename" did the trick.

Still I would like to know if this was the best approach for the situation

Avatar
zenmonkey

17 February 2011 at 10:28am Community Member, 528 Posts

Its a decent method. The only other thing I've ever done is manually build the whole response header when pushing a temporary zip file to the browser, which is even messy-er :)

Avatar
pac

30 September 2011 at 1:13am Community Member, 25 Posts

looks nice but I can't seem to find how to use it in template. can you help ?

Avatar
zenmonkey

30 September 2011 at 2:22am Community Member, 528 Posts

In a template you use $File.Filename to get the path of File. $File.Title will return the name of the file with the dashes converted to spaces. So my-filename becomes "my filename". and $File.Name will return the system filename with dashes

Avatar
ekersten

30 September 2011 at 2:26am Community Member, 16 Posts

In the particular case of the project I was developing, the part of the template that used the controller method on the template looked like this

<% control Songs %>
   <li>
    <span class="title bodoni">{$Pos}. $Title</span>
    <a href="$Top.Link(download)/$SongFile.ID" title="$Title.XML">Download</a>
   </li>
<% end_control %>

I hope this helps.

Avatar
zenmonkey

30 September 2011 at 2:31am Community Member, 528 Posts

What does the Dataobject look like? You're calling $Top but you didn't include the parent control. $Top temporarily breaks you out of the $Songs control loop

Avatar
ekersten

30 September 2011 at 2:36am Community Member, 16 Posts

That's right, it DOES break you out of the $Songs control loop, but that's the whole point since the method I defined is in the controller and not in the model, using $Link inside the $Songs control loop would only give me the link to the current song being listed.

Instead, with $Top, I get the link to the current page and its "download" method, passing also the current $SongFile.ID.

Go to Top