Как запустить загрузку с помощью typo3 / extbase?

Я использую Typo3 с extbase и жидкостью. У меня есть контроллер с действием под названием downloadAction() . После вызова действия система пытается отобразить шаблон загрузки (но я просто хочу начать загрузку).

 public function downloadAction($id) { // create file // send header // dump file // exit } 

Как я могу сбросить созданный download-File и отправить заголовок загрузки вместо обычного процесса рендеринга? Каков наилучший способ?

благодаря

Я сделал это в проекте несколько месяцев назад, это довольно прямолинейно.

  /** * @param string $fileName * @return void */ public function downloadAction($fileName) { $file = $this->settings['uploadFolder'] . 'uploadedPhotos/' . $fileName; if(is_file($file)) { $fileLen = filesize($file); $ext = strtolower(substr(strrchr($fileName, '.'), 1)); switch($ext) { case 'txt': $cType = 'text/plain'; break; case 'pdf': $cType = 'application/pdf'; break; case 'exe': $cType = 'application/octet-stream'; break; case 'zip': $cType = 'application/zip'; break; case 'doc': $cType = 'application/msword'; break; case 'xls': $cType = 'application/vnd.ms-excel'; break; case 'ppt': $cType = 'application/vnd.ms-powerpoint'; break; case 'gif': $cType = 'image/gif'; break; case 'png': $cType = 'image/png'; break; case 'jpeg': case 'jpg': $cType = 'image/jpg'; break; case 'mp3': $cType = 'audio/mpeg'; break; case 'wav': $cType = 'audio/x-wav'; break; case 'mpeg': case 'mpg': case 'mpe': $cType = 'video/mpeg'; break; case 'mov': $cType = 'video/quicktime'; break; case 'avi': $cType = 'video/x-msvideo'; break; //forbidden filetypes case 'inc': case 'conf': case 'sql': case 'cgi': case 'htaccess': case 'php': case 'php3': case 'php4': case 'php5': exit; default: $cType = 'application/force-download'; break; } $headers = array( 'Pragma' => 'public', 'Expires' => 0, 'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0', 'Content-Description' => 'File Transfer', 'Content-Type' => $cType, 'Content-Disposition' => 'attachment; filename="'. $fileName .'"', 'Content-Transfer-Encoding' => 'binary', 'Content-Length' => $fileLen ); foreach($headers as $header => $data) $this->response->setHeader($header, $data); $this->response->sendHeaders(); @readfile($file); } exit; } 

Вы можете определить специальный тип PageType для загрузки:

 download = PAGE download { typeNum = 1249058993 10 < tt_content.list.20.efempty_pi1 config { disableAllHeaderCode = 1 xhtml_cleaning = 0 admPanel = 0 additionalHeaders = Content-type:application/octet-stream } } } 

«efempty» должно быть заменено именем вашего расширения.

Теперь вы можете запускать загрузку следующим образом:

 <f:link.action pageType="1249058993" action="download" controller="ControllerName">Download</f:link.action> 

Обновление : на самом деле это не работает с активированным сжатием, потому что Content-Length по-прежнему будет представлять собой несжатый размер. eID может использоваться в качестве обходного пути, ведь есть даже официальный призыв к этому:

eID = "dumpFile" см. typo3 / sysext / core / Resource / PHP / FileDumpEID.php

Однако этот вызов не заставит загружать, а вместо этого «сбрасывает» его. Я сделал билет @ Forge, чтобы исправить это (что было принято и предназначено для LTS 7): https://forge.typo3.org/issues/67111

Старый ответ : На данный момент самый простой способ добиться этого:

Константы TypoScript

 # ASCII "download" in Numbers (4-15-23-14-12-15-1-4) - See http://rumkin.com/tools/cipher/numbers.php plugin.tx_extensionname.view.formatToPageTypeMapping.download = 4152314121514 

Настройка TypoScript

 tx_extensionname_download = PAGE tx_extensionname_download { typeNum < plugin.tx_extensionname.view.formatToPageTypeMapping.download config { disableAllHeaderCode = 1 xhtml_cleaning = 0 admPanel = 0 debug = 0 no_cache = 1 } 10 = USER 10 { userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run extensionName = ExtensionName pluginName = PluginName vendorName = VENDOR controller = ControllerName action = download view < plugin.tx_extensionname.view persistence < plugin.tx_extensionname.persistence settings < plugin.tx_extensionname.settings } } 

Действие контроллера

 /** * Download * * @param \VENDOR\ExtensionName\Domain\Model\Model $model * @return void * @ignorevalidation $model */ public function downloadAction($model) { if ($model->getFile()) { $model->getFile()->getOriginalResource()->getOriginalFile()->getStorage()->dumpFileContents( $model->getFile()->getOriginalResource(), $asDownload = TRUE, $alternativeFilename = $model->getFile()->getOriginalResource()->getName() ); exit; } $this->throwStatus( $statusCode = 404, $statusMessage = 'Not Found' ); } 

жидкость

 <f:link.action controller="ControllerName" pluginName="PluginName" action="download" arguments="{model: '{model.uid}'}" format="download" title="{model.file.originalResource.title}">Download</f:link.action> 

Выгоды от других упомянутых ответов следующие:

  • Правильные заголовки (включая тим / тип)
  • Форматы extbase вместо typenum

Примечание: iPhone игнорирует заголовки Content-Disposition (всегда встроенные)

О проблемах «выхода» я не тестировал, но с типом страницы он мог бы работать, если бы вы использовали собственный PHPView (StandaloneView?).

Как я могу сбросить созданный файл загрузки и отправить заголовок загрузки вместо обычного процесса рендеринга?

Пока заголовки еще не отправлены , ничто не мешает вам испускать заголовки, отправлять контент и фактически вызывать exit , хотя вы можете проверить буферизацию вывода и очистить все открытые буферы перед этим. Вы также можете просмотреть список заголовков, которые будут отправлены .