public function afterSave($event) { if (!empty($_FILES)) { $model = $this->getOwner(); $file = new File(); $file->filename = UploadUtils::createUniquefilename($_FILES[self::NAME]['name'], UploadUtils::getPath(self::$fileDir)); if (move_uploaded_file($_FILES[self::NAME]['tmp_name'], UploadUtils::getPath(self::$fileDir) . DIRECTORY_SEPARATOR . $file->filename)) { $file->entity = get_class($model); $file->EXid = $model->getPrimaryKey(); $file->uid = Yii::app()->user->id; $file->tag = $this->tag; $file->weight = 0; $file->timestamp = time(); $file->filemime = CFileHelper::getMimeTypeByExtension($_FILES[self::NAME]['name']); $file->filesize = $_FILES[self::NAME]['size']; $file->status = File::STATUS_SAVED; // Ensure all other files of the entity are deleted //UploadUtils::deleteAllFiles(get_class($this->getOwner()), self::$fileDir); if ($file->save()) { Yii::trace("File saved " . $file . "!!!!"); } else { Yii::log("Could not save File " . print_r($file->getErrors(), true), CLogger::LEVEL_ERROR); } } else { Yii::log("Couldnt move the file", CLogger::LEVEL_ERROR); } } else { Yii::log("Files empty!!!", CLogger::LEVEL_ERROR); } }
/** * @param CUploadedFile $image * @return bool */ public static function isAllowedType(CUploadedFile $image) { $type = CFileHelper::getMimeType($image->getTempName()); if (!$type) { $type = CFileHelper::getMimeTypeByExtension($image->getName()); } return in_array($type, EventsImagesConfig::get('types')); }
/** * @param CUploadedFile $image * @return bool */ public static function isAllowedType(CUploadedFile $image) { $type = CFileHelper::getMimeType($image->getTempName()); if (!$type) { $type = CFileHelper::getMimeTypeByExtension($image->getName()); } return in_array($type, array('image/gif', 'image/jpeg', 'image/pjpeg', 'image/png', 'image/x-png')); }
/** * @param CUploadedFile $image * @return bool */ public static function isAllowedType(CUploadedFile $image) { $type = CFileHelper::getMimeType($image->getTempName()); if (!$type) { $type = CFileHelper::getMimeTypeByExtension($image->getName()); } //return in_array($type, Yii::app()->params['storeImages']['types']); return in_array($type, StoreImagesConfig::get('types')); }
public function testGetMimeTypeByExtension() { // run everything ten times in one test action to be sure that caching inside // CFileHelper::getMimeTypeByExtension() is working the right way for ($i = 0; $i < 10; $i++) { $this->assertNull(CFileHelper::getMimeTypeByExtension('test.txa')); $this->assertNull(CFileHelper::getMimeTypeByExtension('test.txb')); $this->assertEquals('text/plain', CFileHelper::getMimeTypeByExtension('test.txt')); $this->assertEquals('application/json', CFileHelper::getMimeTypeByExtension('test.txa', $this->testDir . 'mimeTypes1.php')); $this->assertEquals('another/mime', CFileHelper::getMimeTypeByExtension('test.txb', $this->testDir . 'mimeTypes1.php')); $this->assertNull(CFileHelper::getMimeTypeByExtension('test.txt', $this->testDir . 'mimeTypes1.php')); $this->assertNull(CFileHelper::getMimeTypeByExtension('test.txa', $this->testDir . 'mimeTypes2.php')); $this->assertEquals('another/mime2', CFileHelper::getMimeTypeByExtension('test.txb', $this->testDir . 'mimeTypes2.php')); $this->assertEquals('text/plain', CFileHelper::getMimeTypeByExtension('test.txt', $this->testDir . 'mimeTypes2.php')); } }
private function writeHeader() { $this->checkResumeDownload(); //Inicia checando se irá ou não resumir um download já iniciado $disposition = $this->force ? 'attachment' : 'inline'; header('Content-Description: File Transfer'); header('Content-Disposition: ' . $disposition . '; filename="' . $this->filename . '"'); header('Content-Transfer-Encoding: binary'); header('Cache-Control: public, must-revalidate, max-age=0'); header('Pragma: no-cache'); //header('Pragma: public'); header('Accept-Ranges: bytes'); header('Expires: 0'); if ($this->_dummy) { header('Content-Type: ' . CFileHelper::getMimeTypeByExtension($this->_file)); } else { header('Content-Type: ' . CFileHelper::getMimeType($this->_file)); header("Content-Length: " . ($this->_size - $this->_begin)); $contentRange = "Content-Range: bytes {$this->_begin}-" . ($this->_size - 1) . "/{$this->_size}"; header($contentRange); } ob_clean(); flush(); }
public function xSendFile($filePath, $options = array()) { if (!is_file($filePath)) { return false; } if (!isset($options['saveName'])) { $options['saveName'] = basename($filePath); } if (!isset($options['mimeType'])) { if (($options['mimeType'] = CFileHelper::getMimeTypeByExtension($filePath)) === null) { $options['mimeType'] = 'text/plain'; } } if (!isset($options['xHeader'])) { $options['xHeader'] = 'X-Sendfile'; } header('Content-type: ' . $options['mimeType']); header('Content-Disposition: attachment; filename="' . $options['saveName'] . '"'); header(trim($options['xHeader']) . ': ' . $filePath); if (!isset($options['terminate']) || $options['terminate']) { Yii::app()->end(); } return true; }
public function sendFile($fileName, $content, $mimeType = null, $terminate = true) { if ($mimeType === null) { if (($mimeType = CFileHelper::getMimeTypeByExtension($fileName)) === null) { $mimeType = 'text/plain'; } } header('Pragma: public'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header("Content-type: {$mimeType}"); if (ini_get("output_handler") == '') { header('Content-Length: ' . (function_exists('mb_strlen') ? mb_strlen($content, '8bit') : strlen($content))); } header("Content-Disposition: attachment; filename=\"{$fileName}\""); header('Content-Transfer-Encoding: binary'); if ($terminate) { // clean up the application first because the file downloading could take long time // which may cause timeout of some resources (such as DB connection) Yii::app()->end(0, false); echo $content; exit(0); } else { echo $content; } }
/** * Sends a file to the user. * * We’re overriding this from {@link \CHttpRequest::sendFile()} so we can have more control over the headers. * * @param string $path The path to the file on the server. * @param string $content The contents of the file. * @param array|null $options An array of optional options. Possible keys include 'forceDownload', 'mimeType', * and 'cache'. * @param bool|null $terminate Whether the request should be terminated after the file has been sent. * Defaults to `true`. * * @throws HttpException * @return null */ public function sendFile($path, $content, $options = array(), $terminate = true) { $fileName = IOHelper::getFileName($path, true); // Clear the output buffer to prevent corrupt downloads. Need to check the OB status first, or else some PHP // versions will throw an E_NOTICE since we have a custom error handler // (http://pear.php.net/bugs/bug.php?id=9670) if (ob_get_length() !== false) { // If zlib.output_compression is enabled, then ob_clean() will corrupt the results of output buffering. // ob_end_clean is what we want. ob_end_clean(); } // Default to disposition to 'download' $forceDownload = !isset($options['forceDownload']) || $options['forceDownload']; if ($forceDownload) { HeaderHelper::setDownload($fileName); } if (empty($options['mimeType'])) { if (($options['mimeType'] = \CFileHelper::getMimeTypeByExtension($fileName)) === null) { $options['mimeType'] = 'text/plain'; } } HeaderHelper::setHeader(array('Content-Type' => $options['mimeType'] . '; charset=utf-8')); $fileSize = mb_strlen($content, '8bit'); $contentStart = 0; $contentEnd = $fileSize - 1; $httpVersion = $this->getHttpVersion(); if (isset($_SERVER['HTTP_RANGE'])) { HeaderHelper::setHeader(array('Accept-Ranges' => 'bytes')); // Client sent us a multibyte range, can not hold this one for now if (mb_strpos($_SERVER['HTTP_RANGE'], ',') !== false) { HeaderHelper::setHeader(array('Content-Range' => 'bytes ' . $contentStart - $contentEnd / $fileSize)); throw new HttpException(416, 'Requested Range Not Satisfiable'); } $range = str_replace('bytes=', '', $_SERVER['HTTP_RANGE']); // range requests starts from "-", so it means that data must be dumped the end point. if ($range[0] === '-') { $contentStart = $fileSize - mb_substr($range, 1); } else { $range = explode('-', $range); $contentStart = $range[0]; // check if the last-byte-pos presents in header if (isset($range[1]) && is_numeric($range[1])) { $contentEnd = $range[1]; } } // Check the range and make sure it's treated according to the specs. // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html // End bytes can not be larger than $end. $contentEnd = $contentEnd > $fileSize ? $fileSize - 1 : $contentEnd; // Validate the requested range and return an error if it's not correct. $wrongContentStart = $contentStart > $contentEnd || $contentStart > $fileSize - 1 || $contentStart < 0; if ($wrongContentStart) { HeaderHelper::setHeader(array('Content-Range' => 'bytes ' . $contentStart - $contentEnd / $fileSize)); throw new HttpException(416, 'Requested Range Not Satisfiable'); } HeaderHelper::setHeader("HTTP/{$httpVersion} 206 Partial Content"); HeaderHelper::setHeader(array('Content-Range' => 'bytes ' . $contentStart - $contentEnd / $fileSize)); } else { HeaderHelper::setHeader("HTTP/{$httpVersion} 200 OK"); } // Calculate new content length $length = $contentEnd - $contentStart + 1; if (!empty($options['cache'])) { $cacheTime = 31536000; // 1 year HeaderHelper::setHeader(array('Expires' => gmdate('D, d M Y H:i:s', time() + $cacheTime) . ' GMT')); HeaderHelper::setHeader(array('Pragma' => 'cache')); HeaderHelper::setHeader(array('Cache-Control' => 'max-age=' . $cacheTime)); $modifiedTime = IOHelper::getLastTimeModified($path); HeaderHelper::setHeader(array('Last-Modified' => gmdate("D, d M Y H:i:s", $modifiedTime->getTimestamp()) . ' GMT')); } else { if (!$forceDownload) { HeaderHelper::setNoCache(); } else { // Fixes a bug in IE 6, 7 and 8 when trying to force download a file over SSL: // https://stackoverflow.com/questions/1218925/php-script-to-download-file-not-working-in-ie HeaderHelper::setHeader(array('Pragma' => '', 'Cache-Control' => '')); } } if ($options['mimeType'] == 'application/x-javascript' || $options['mimeType'] == 'text/css') { HeaderHelper::setHeader(array('Vary' => 'Accept-Encoding')); } if (!ob_get_length()) { HeaderHelper::setLength($length); } $content = mb_substr($content, $contentStart, $length); if ($terminate) { // Clean up the application first because the file downloading could take long time which may cause timeout // of some resources (such as DB connection) ob_start(); Craft::app()->end(0, false); ob_end_clean(); echo $content; exit(0); } else { echo $content; } }
/** * Sends a file to user. * @param string file name * @param string content to be set. * @param string mime type of the content. If null, it will be guessed automatically based on the given file name. * @param boolean whether to terminate the current application after calling this method */ public function sendFile($fileName, $content, $mimeType = null, $terminate = true) { if ($mimeType === null) { if (($mimeType = CFileHelper::getMimeTypeByExtension($fileName)) === null) { $mimeType = 'text/plain'; } } header('Pragma: public'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header("Content-type: {$mimeType}"); header('Content-Length: ' . strlen($content)); header("Content-Disposition: attachment; filename=\"{$fileName}\""); header('Content-Transfer-Encoding: binary'); echo $content; if ($terminate) { Yii::app()->end(); } }
/** * Initialize ExtMinScriptSource. * @param array $options Initialization options. */ public function __construct($options) { if (isset($options['filepath'])) { $this->contentType = CFileHelper::getMimeTypeByExtension($options['filepath']); $this->filepath = $options['filepath']; $this->_id = $options['filepath']; $this->lastModified = isset($options['lastModified']) ? $options['lastModified'] : time(); $this->minifier = isset($options['minifier']) ? $options['minifier'] : null; } }
public function run() { // Settings // --------------------- $targetDir = UploadWidget::$tempDir; // --------------------- $cleanupTargetDir = false; // Remove old files $maxFileAge = 60 * 60; // Temp file age in seconds // 5 minutes execution time @set_time_limit(5 * 60); // usleep(5000); // Get parameters $chunk = isset($_REQUEST["chunk"]) ? $_REQUEST["chunk"] : 0; $chunks = isset($_REQUEST["chunks"]) ? $_REQUEST["chunks"] : 0; $fileName = isset($_REQUEST["name"]) ? $_REQUEST["name"] : ''; // Create unique filename $fileName = UploadUtils::createUniquefilename($fileName, $targetDir); // Create target dir if (!file_exists($targetDir)) { @mkdir($targetDir); } // Remove old temp files if (is_dir($targetDir) && ($dir = opendir($targetDir))) { while (($file = readdir($dir)) !== false) { $filePath = $targetDir . DIRECTORY_SEPARATOR . $file; // Remove temp files if they are older than the max age if (preg_match('/\\.tmp$/', $file) && filemtime($filePath) < time() - $maxFileAge) { @unlink($filePath); } } closedir($dir); } else { die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory."}, "id" : "id"}'); } // Look for the content type header if (isset($_SERVER["HTTP_CONTENT_TYPE"])) { $contentType = $_SERVER["HTTP_CONTENT_TYPE"]; } if (isset($_SERVER["CONTENT_TYPE"])) { $contentType = $_SERVER["CONTENT_TYPE"]; } if (strpos($contentType, "multipart") !== false) { if (isset($_FILES['file']['tmp_name']) && is_uploaded_file($_FILES['file']['tmp_name'])) { // Open temp file $out = fopen($targetDir . DIRECTORY_SEPARATOR . $fileName, $chunk == 0 ? "wb" : "ab"); if ($out) { // Read binary input stream and append it to temp file $in = fopen($_FILES['file']['tmp_name'], "rb"); if ($in) { while ($buff = fread($in, 4096)) { fwrite($out, $buff); } } else { die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}'); } fclose($out); unlink($_FILES['file']['tmp_name']); } else { die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}'); } } else { die('{"jsonrpc" : "2.0", "error" : {"code": 103, "message": "Failed to move uploaded file."}, "id" : "id"}'); } } else { // Open temp file $out = fopen($targetDir . DIRECTORY_SEPARATOR . $fileName, $chunk == 0 ? "wb" : "ab"); if ($out) { // Read binary input stream and append it to temp file $in = fopen("php://input", "rb"); if ($in) { while ($buff = fread($in, 4096)) { fwrite($out, $buff); } } else { die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}'); } fclose($out); } else { die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}'); } } // --------------------- // Save the file to db $file = new File(); //$file->entity = get_class($this->getOwner()); $file->EXid = -1; $file->uid = Yii::app()->user->id; $file->tag = $_REQUEST['tag']; $file->weight = 0; $file->timestamp = time(); // Because flash labels everything with app/octet-stream // $file->filemime = $_FILES['Filedata']['type']; $file->filemime = CFileHelper::getMimeTypeByExtension($targetDir . DIRECTORY_SEPARATOR . $fileName); $file->filesize = filesize($targetDir . DIRECTORY_SEPARATOR . $fileName); $file->status = File::STATUS_TEMP; $file->filename = $fileName; // Store it in session UploadUtils::addFileToSession($file); // --------------------- // Return JSON-RPC response die('{"jsonrpc" : "2.0", "result" : null, "id" : "id"}'); }
/** * Returns the file mime type. * @return string the file mime type. * @throws CException if the mime type cannot be determined. */ public function getMimeType() { if (($mimeType = CFileHelper::getMimeTypeByExtension($this->resolveFilename())) !== null) { return $mimeType; } throw new CException(sprintf('Failed to determine mime type for file "%s"', $this->resolveFilename())); }
/** * Renders an image from P2File specified by id and preset * * @param integer $id * @param string $preset * @return mixed Rendering result, false if an error occured, otherwise an array with 'type' and 'data' */ public static function processMediaFile($id, $preset) { Yii::trace('Processing media file #' . $id . ' ...', 'p2.file'); // get file from db $model = self::findModel($id); if (!$model) { return false; } // look for mapping - TODO: separate method ... $inFile = Yii::getPathOfAlias(Yii::app()->controller->module->dataAlias) . DIRECTORY_SEPARATOR . $model->path; /* if (is_array(Yii::app()->params['p2.file.pathMappings'])) foreach(Yii::app()->params['p2.file.pathMappings'] AS $oldPath => $newPath){ if (substr($model->filePath,0,strlen($oldPath)) == $oldPath) { $inFile = Yii::app()->basePath . DIRECTORY_SEPARATOR . str_replace($oldPath, $newPath, $model->filePath); } } */ $path = self::prepareRenderPath($preset['savePublic']); if (is_file($inFile)) { if ($preset['originalFile'] === true) { // return original file and exit self::sendImage($inFile, $model, $preset); } $hash = self::generateHash($model, $preset); $outFile = $path . DIRECTORY_SEPARATOR . $hash; if (is_file($outFile)) { // file exists #Yii::trace('found existing file.', 'p2.file'); } else { Yii::log('Creating image from ' . $inFile, CLogger::LEVEL_INFO, 'p2.file'); if (!self::generateImage($inFile, $outFile, $preset)) { Yii::log('Error while rendering ' . $inFile, CLogger::LEVEL_INFO, 'p2.file'); $mimeImageDir = Yii::getPathOfAlias('p3media.images.mimetypes'); $mimeImageFile = $mimeImageDir . DIRECTORY_SEPARATOR . CFileHelper::getMimeTypeByExtension($inFile) . '.png'; #echo $mimeImageFile;exit; if (!is_file($mimeImageFile)) { Yii::log('Missing mime type image ' . $mimeImageFile, CLogger::LEVEL_WARNING, 'p2.file'); $mimeImageFile = $mimeImageDir . DIRECTORY_SEPARATOR . "mime-empty.png"; } self::generateImage($mimeImageFile, $outFile, $preset); } } } else { Yii::log("File #{$id} {$inFile} missing! [uniqid:" . uniqid() . "]", CLogger::LEVEL_WARNING, 'p2.file'); // TODO: log message appears twice return false; } $info = getimagesize($outFile); // output if ($preset['savePublic'] === true) { return array('type' => 'public', 'data' => Yii::app()->baseUrl . Yii::app()->controller->module->params['publicRuntimeUrl'] . "/" . $hash, 'info' => $info); } else { return array('type' => 'protected', 'data' => $outFile, 'info' => $info); } }
/** * Renders an image from P2File specified by id and preset * * @param array/integer $identifier * @param string $preset * @return mixed Rendering result, false if an error occured, otherwise an array with 'type' and 'data' */ public static function processMediaFile($identifier, $preset) { if (is_integer($identifier)) { $identifier = array('id' => $identifier); } Yii::trace('Processing media file with ' . key($identifier) . ' "' . $identifier[key($identifier)] . '" ...', 'p3pages.actions.P3MediaImageAction'); // get file from db $model = self::findModel($identifier); if (!$model) { return false; } $inFile = Yii::getPathOfAlias(Yii::app()->controller->module->dataAlias) . DIRECTORY_SEPARATOR . $model->path; $path = self::prepareRenderPath($preset['savePublic']); if (is_file($inFile)) { $hash = self::generateHash($model, $preset); $outFile = $path . DIRECTORY_SEPARATOR . $hash; if ($preset['originalFile'] === true) { // return original file and exit if ($preset['savePublic'] === true) { copy($inFile, $outFile); //echo str_replace(Yii::app()->basePath, Yii::app()->baseUrl, $outFile);exit; $outUrl = str_replace(DIRECTORY_SEPARATOR, "/", $outFile); header('location: ' . str_replace(Yii::app()->basePath, Yii::app()->baseUrl, $outUrl)); //self::sendImage($outFile, $model, $preset); } else { self::sendImage($inFile, basename($model->title), $preset); } } if (is_file($outFile)) { // file exists #Yii::trace('found existing file.', 'p3pages.actions.P3MediaImageAction'); } else { Yii::log('Creating image from ' . $inFile, CLogger::LEVEL_INFO, 'p3pages.actions.P3MediaImageAction'); if (!self::generateImage($inFile, $outFile, $preset)) { Yii::log('Error while rendering ' . $inFile, CLogger::LEVEL_INFO, 'p3pages.actions.P3MediaImageAction'); $mimeImageDir = Yii::getPathOfAlias('p3media.images.mimetypes'); $mimeImageFile = $mimeImageDir . DIRECTORY_SEPARATOR . CFileHelper::getMimeTypeByExtension($inFile) . '.png'; #echo $mimeImageFile;exit; if (!is_file($mimeImageFile)) { Yii::log('Missing mime type image ' . $mimeImageFile, CLogger::LEVEL_WARNING, 'p3pages.actions.P3MediaImageAction'); $mimeImageFile = $mimeImageDir . DIRECTORY_SEPARATOR . "mime-empty.png"; } self::generateImage($mimeImageFile, $outFile, $preset); } } } else { Yii::log("File " . key($identifier) . "=>" . $identifier[key($identifier)] . " {$inFile} missing! [uniqid:" . uniqid() . "]", CLogger::LEVEL_WARNING, 'p3pages.actions.P3MediaImageAction'); // TODO: log message appears twice return false; } $info = getimagesize($outFile); // output if ($preset['savePublic'] === true) { return array('type' => 'public', 'data' => Yii::app()->baseUrl . Yii::app()->getModule('p3media')->params['publicRuntimeUrl'] . "/" . $hash, 'info' => $info); } else { return array('type' => 'protected', 'data' => $outFile, 'info' => $info); } }
/** * A wrapper for {@link \CFileHelper::getMimeTypeByExtension}. * * @param string $path The path to test. * * @return string The mime type. */ public static function getMimeTypeByExtension($path) { return \CFileHelper::getMimeTypeByExtension($path); }
/** * Sends existing file to a browser as a download using x-sendfile. * * X-Sendfile is a feature allowing a web application to redirect the request for a file to the webserver * that in turn processes the request, this way eliminating the need to perform tasks like reading the file * and sending it to the user. When dealing with a lot of files (or very big files) this can lead to a great * increase in performance as the web application is allowed to terminate earlier while the webserver is * handling the request. * * The request is sent to the server through a special non-standard HTTP-header. * When the web server encounters the presence of such header it will discard all output and send the file * specified by that header using web server internals including all optimizations like caching-headers. * * As this header directive is non-standard different directives exists for different web servers applications: * <ul> * <li>Apache: {@link http://tn123.org/mod_xsendfile X-Sendfile}</li> * <li>Lighttpd v1.4: {@link http://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file X-LIGHTTPD-send-file}</li> * <li>Lighttpd v1.5: {@link http://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file X-Sendfile}</li> * <li>Nginx: {@link http://wiki.nginx.org/XSendfile X-Accel-Redirect}</li> * <li>Cherokee: {@link http://www.cherokee-project.com/doc/other_goodies.html#x-sendfile X-Sendfile and X-Accel-Redirect}</li> * </ul> * So for this method to work the X-SENDFILE option/module should be enabled by the web server and * a proper xHeader should be sent. * * <b>Note:</b> * This option allows to download files that are not under web folders, and even files that are otherwise protected (deny from all) like .htaccess * * <b>Side effects</b>: * If this option is disabled by the web server, when this method is called a download configuration dialog * will open but the downloaded file will have 0 bytes. * * <b>Example</b>: * <pre> * <?php * Yii::app()->request->xSendFile('/home/user/Pictures/picture1.jpg',array( * 'saveName'=>'image1.jpg', * 'mimeType'=>'image/jpeg', * 'terminate'=>false, * )); * ?> * </pre> * @param string $filePath file name with full path * @param array $options additional options: * <ul> * <li>saveName: file name shown to the user, if not set real file name will be used</li> * <li>mimeType: mime type of the file, if not set it will be guessed automatically based on the file name, if set to null no content-type header will be sent.</li> * <li>xHeader: appropriate x-sendfile header, defaults to "X-Sendfile"</li> * <li>terminate: whether to terminate the current application after calling this method, defaults to true</li> * <li>forceDownload: specifies whether the file will be downloaded or shown inline, defaults to true. (Since version 1.1.9.)</li> * <li>addHeaders: an array of additional http headers in header-value pairs (available since version 1.1.10)</li> * </ul> */ public function xSendFile($filePath, $options = array()) { if (!isset($options['forceDownload']) || $options['forceDownload']) { $disposition = 'attachment'; } else { $disposition = 'inline'; } if (!isset($options['saveName'])) { $options['saveName'] = basename($filePath); } if (!isset($options['mimeType'])) { if (($options['mimeType'] = CFileHelper::getMimeTypeByExtension($filePath)) === null) { $options['mimeType'] = 'text/plain'; } } if (!isset($options['xHeader'])) { $options['xHeader'] = 'X-Sendfile'; } if ($options['mimeType'] !== null) { header('Content-type: ' . $options['mimeType']); } header('Content-Disposition: ' . $disposition . '; filename="' . $options['saveName'] . '"'); if (isset($options['addHeaders'])) { foreach ($options['addHeaders'] as $header => $value) { header($header . ': ' . $value); } } header(trim($options['xHeader']) . ': ' . $filePath); if (!isset($options['terminate']) || $options['terminate']) { Yii::app()->end(); } }
/** * Sends a file to the user. * * We're overriding this from \CHttpRequest so we can have more control over the headers. * * @param string $path * @param string $content * @param array|null $options * @param bool|null $terminate */ public function sendFile($path, $content, $options = array(), $terminate = true) { $fileName = IOHelper::getFileName($path, true); // Clear the output buffer to prevent corrupt downloads. // Need to check the OB status first, or else some PHP versions will throw an E_NOTICE since we have a custom error handler // (http://pear.php.net/bugs/bug.php?id=9670) if (ob_get_length() !== false) { ob_clean(); } // Default to disposition to 'download' if (!isset($options['forceDownload']) || $options['forceDownload']) { header('Content-Disposition: attachment; filename="' . $fileName . '"'); } if (empty($options['mimeType'])) { if (($options['mimeType'] = \CFileHelper::getMimeTypeByExtension($fileName)) === null) { $options['mimeType'] = 'text/plain'; } } header('Content-type: ' . $options['mimeType']); if (!empty($options['cache'])) { $cacheTime = 31536000; // 1 year header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $cacheTime) . ' GMT'); header('Pragma: cache'); header('Cache-Control: max-age=' . $cacheTime); $modifiedTime = IOHelper::getLastTimeModified($path); header('Last-Modified: ' . gmdate("D, d M Y H:i:s", $modifiedTime->getTimestamp()) . ' GMT'); } else { header('Pragma: public'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); } if (!ob_get_length()) { header('Content-Length: ' . (function_exists('mb_strlen') ? mb_strlen($content, '8bit') : strlen($content))); } if ($options['mimeType'] == 'application/x-javascript' || $options['mimeType'] == 'text/css') { header('Vary: Accept-Encoding'); } if ($terminate) { // clean up the application first because the file downloading could take long time // which may cause timeout of some resources (such as DB connection) ob_start(); Craft::app()->end(0, false); ob_end_clean(); echo $content; exit(0); } else { echo $content; } }