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   2929 Views

Avatar
ekersten

Community Member, 16 Posts

17 February 2011 at 3:52am

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

Community Member, 16 Posts

17 February 2011 at 4:04am

Edited: 17/02/2011 4:06am

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

Community Member, 532 Posts

17 February 2011 at 10:28am

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

Community Member, 25 Posts

30 September 2011 at 1:13am

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

Avatar
zenmonkey

Community Member, 532 Posts

30 September 2011 at 2:22am

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

Community Member, 16 Posts

30 September 2011 at 2:26am

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

Community Member, 532 Posts

30 September 2011 at 2:31am

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

Community Member, 16 Posts

30 September 2011 at 2:36am

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