|  |  | @ -10,6 +10,7 @@ namespace yii\web; | 
			
		
	
		
		
			
				
					
					|  |  |  | use Yii; |  |  |  | use Yii; | 
			
		
	
		
		
			
				
					
					|  |  |  | use yii\helpers\FileHelper; |  |  |  | use yii\helpers\FileHelper; | 
			
		
	
		
		
			
				
					
					|  |  |  | use yii\helpers\Html; |  |  |  | use yii\helpers\Html; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | use yii\helpers\StringHelper; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /** |  |  |  | /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  * @author Qiang Xue <qiang.xue@gmail.com> |  |  |  |  * @author Qiang Xue <qiang.xue@gmail.com> | 
			
		
	
	
		
		
			
				
					|  |  | @ -35,23 +36,81 @@ class Response extends \yii\base\Response | 
			
		
	
		
		
			
				
					
					|  |  |  | 	 */ |  |  |  | 	 */ | 
			
		
	
		
		
			
				
					
					|  |  |  | 	public function sendFile($fileName, $content, $mimeType = null, $terminate = true) |  |  |  | 	public function sendFile($fileName, $content, $mimeType = null, $terminate = true) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	{ |  |  |  | 	{ | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if ($mimeType === null && ($mimeType = FileHelper::getMimeType($fileName)) === null) { |  |  |  | 		if ($mimeType === null) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			$mimeType = 'application/octet-stream'; |  |  |  | 			if (($mimeType = FileHelper::getMimeTypeByExtension($fileName)) === null) { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				$mimeType='application/octet-stream'; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		$fileSize = StringHelper::strlen($content); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		$contentStart = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		$contentEnd = $fileSize - 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		if (isset($_SERVER['HTTP_RANGE'])) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			header('Accept-Ranges: bytes'); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			//client sent us a multibyte range, can not hold this one for now | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			if (strpos(',', $_SERVER['HTTP_RANGE']) !== false) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				header('HTTP/1.1 416 Requested Range Not Satisfiable'); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				header("Content-Range: bytes $contentStart-$contentEnd/$fileSize"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				ob_start(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				Yii::app()->end(0,false); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				ob_end_clean(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				exit(0); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			$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 - substr($range, 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			} else { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				$range = explode('-', $range); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				$contentStart = $range[0]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				$contentEnd = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $fileSize; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			/* 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 : $contentEnd; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			// Validate the requested range and return an error if it's not correct. | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			$wrongContentStart = ($contentStart > $contentEnd || $contentStart > $fileSize - 1 || $contentStart < 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			if ($wrongContentStart) {    | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				header('HTTP/1.1 416 Requested Range Not Satisfiable'); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				header("Content-Range: bytes $contentStart-$contentEnd/$fileSize"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				ob_start(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				Yii::app()->end(0,false); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				ob_end_clean(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 				exit(0); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			header('HTTP/1.1 206 Partial Content'); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			header("Content-Range: bytes $contentStart-$contentEnd/$fileSize"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		} else { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			header('HTTP/1.1 200 OK'); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  | 		} | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		$length = $contentEnd - $contentStart + 1; // Calculate new content length | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		header('Pragma: public'); |  |  |  | 		header('Pragma: public'); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		header('Expires: 0'); |  |  |  | 		header('Expires: 0'); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); |  |  |  | 		header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		header("Content-type: $mimeType"); |  |  |  | 		header("Content-type: $mimeType"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if (ob_get_length() === false) { |  |  |  | 		header('Content-Length: '.$length); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			header('Content-Length: ' . (function_exists('mb_strlen') ? mb_strlen($content, '8bit') : strlen($content))); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		header("Content-Disposition: attachment; filename=\"$fileName\""); |  |  |  | 		header("Content-Disposition: attachment; filename=\"$fileName\""); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		header('Content-Transfer-Encoding: binary'); |  |  |  | 		header('Content-Transfer-Encoding: binary'); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 		$content = StringHelper::strlen($content); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if ($terminate) { |  |  |  | 		if ($terminate) { | 
			
		
	
		
		
			
				
					
					|  |  |  | 			// clean up the application first because the file downloading could take long time |  |  |  | 			// clean up the application first because the file downloading could take long time | 
			
		
	
		
		
			
				
					
					|  |  |  | 			// which may cause timeout of some resources (such as DB connection) |  |  |  | 			// which may cause timeout of some resources (such as DB connection) | 
			
		
	
		
		
			
				
					
					|  |  |  | 			Yii::app()->end(0, false); |  |  |  | 			ob_start(); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			Yii::app()->end(0,false); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 			ob_end_clean(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 			echo $content; |  |  |  | 			echo $content; | 
			
		
	
		
		
			
				
					
					|  |  |  | 			exit(0); |  |  |  | 			exit(0); | 
			
		
	
		
		
			
				
					
					|  |  |  | 		} else { |  |  |  | 		} else { | 
			
		
	
	
		
		
			
				
					|  |  | 
 |