> I really don't thinkit's necessary to start throwing HTTP headers for a PDF download
The problem is if the PDF files are big and/or the server is slow, the browser gives no progress indication, so after 5 seconds, people give up and click Back. If it's a download, then they get a pop-up as soon as they click, then they get progress indication. Far more users see the download through to completion.
> send_file() is a function on HTTPRequest not HTTPResponse.
True, SS_HTTPRequest::send_file works for me.
OK, here's a working example, using SilverStripe 2.4.5
I have multiple DataObject classes that have a file field called Document (among other fields of course)...
class NewsObject extends DataObject {
public static $has_one = array(
'Document' => 'File'
);
public function getCMSFields_forPopup() {
new FileIFrameField('Document', 'File', null, null, null, self::$defaultFileFolder)
);
}
In the Page_Controller, I add a download action for each of the DataObject classes...
class Page_Controller extends ContentController {
public static $allowed_actions = array (
'downloadevent', 'downloadnews'
);
.
.
.
private function download($classname) {
$id = intval( Director::URLParam('ID') );
$object = $id ? DataObject::get_one($classname, 'ID=' . $id ) : null;
$document = $object ? $object->Document() : null;
if ( $document )
return SS_HTTPRequest::send_file(file_get_contents($document->getFullPath()), $document->getFilename() );
else
return $this->httpError(404);
}
public function downloadevent() {
return $this->download('EventObject');
}
public function downloadnews() {
return $this->download('NewsObject');
}
function BaseUrl() {
return Director::baseURL() . $this->URLSegment;
}
}
...so all page types inherit the download functionality, and the download actions can be used in any .ss file...
<% control NewsObjects %>
<a href="$Top.BaseUrl/downloadnews/$ID">
<% end_control %>
<% control EventObjects %>
<a href="$Top.BaseUrl/downloadevent/$ID">
<% end_control %>