2012-02-16 29 views
2
class Transfer { 

/** 
* @access private 
* @var integer 
*/ 
private $mDownStart; 

/** 
* @access private 
* @var integer 
*/ 
private $mFileSize; 

/** 
* @access private 
* @var integer 
*/ 
private $mFileHandle; 

/** 
* @access private 
* @var string 
*/ 
private $mFilePath; 

/** 
* @access private 
* @var string 
*/ 
private $mFileName; 

/** 
* @access public 
* @return void 
**/ 
public function __construct() { 
} 

/** 
* @access public 
* @return void 
**/ 
public function Down($pFilePath, $pFileName = '') { 
    $this->mFilePath = $pFilePath; 
    if (!$this->iniFile()) 
     $this->sendError(); 
    $this->mFileName = empty($pFileName) ? $this->getFileName() : $pFileName; 

    $this->iniFile(); 
    $this->setStart(); 
    $this->setHeader(); 

    $this->send(); 

    fclose($this->mFileHandle); 
} 

/** 
* @access private 
* @return boolean 
**/ 
private function iniFile() { 
    if (!is_file($this->mFilePath)) 
     return false; 
    $this->mFileHandle = fopen($this->mFilePath, 'rb'); 
    $this->mFileSize = filesize($this->mFilePath); 
    return true; 
} 

/** 
* @access private 
* @return void 
**/ 
private function setStart() { 
    if (isset($_SERVER['HTTP_RANGE'])) { 
     preg_match("/^bytes=([0-9]+)-$/i", $_SERVER['HTTP_RANGE'], $match); 
     $this->mDownStart = $match[1]; 
     fseek($this->mFileHandle, $this->mDownStart); 
    } else { 
     $this->mDownStart = 0; 
    } 
} 

/** 
* @access private 
* @return void 
**/ 
private function setHeader() { 
    @header("Cache-control: public"); 
    @header("Pragma: public"); 
    header("Content-Length: " . ($this->mFileSize - $this->mDownStart)); 
    if ($this->mDownStart > 0) { 
     @header("HTTP/1.1 206 Partial Content"); 
     header("Content-Range: bytes " . $this->mDownStart . "-" . ($this->mFileSize - 1) . "/" . $this->mFileSize); 
    } else { 
     header("Accept-Range: bytes"); 
    } 
    @header("Content-Type: application/octet-stream"); 
    @header("Content-Disposition: attachment;filename=" . $this->mFileName); 
} 

/** 
* @access private 
* @return string 
**/ 
private function getFileName() { 
    return basename($this->mFilePath); 
} 

/** 
* @access private 
* @return void 
**/ 
private function send() { 
    // fpassthru($this->mFileHandle); 

    while (!feof($this->mFileHandle)) { 
     set_time_limit(0); 
     $buffer = fread($this->mFileHandle, 1024 * 1024); 
     echo $buffer; 
     flush(); 
     ob_flush(); 
    } 
} 

/** 
* @access public 
* @return void 
**/ 
public function sendError() { 
    @header("HTTP/1.0 404 Not Found"); 
    @header("Status: 404 Not Found"); 
    exit(); 
} 
} 

这里下载文件多是我如何使用它,使用PHP一次

$transfer = new Transfer; 
$transfer->Down('D:\Pro lab\Aptana workspace\ezine\ezine\201202161811\VOL_001_201202161811.zip'); 

当我尝试打开IE的两个标签来运行该脚本。但是,他们不能同时下载。他们是在一个接一个的顺序。 但是,当我把文件放在apache根目录下。仍然使用IE的两个标签下载它们,它们可以同时下载。 我想知道为什么会发生这种情况?

我猜如果在PHP中有任何一种“锁定”,限制同一个客户端同时下载相同的资源??

+1

您是否有强制会话在子目录中启动的.htaccess或其他重写?如果存在活动会话,则一次只能有一个连接工作 - 其他连接将阻塞,直到会话被释放。 – 2012-02-16 14:54:08

+0

我认为,这里没有活动会话。 – 2012-02-16 15:07:28

+1

我想这不是一个下载的东西,它是一个PHP的东西。为了防止每个会话负载过重(并且每个通过http的呼叫都是会话),可能会同时执行一个脚本。您可以将文件写入临时文件夹并直接重定向到该文件,而不是通过PHP传递整个文件。 – Armin 2012-02-16 15:13:31

回答

0

如果您尝试从两个窗口访问相同的脚本并锁定第二个脚本,则在大多数情况下,这是会话锁定的指示。你在使用会话吗?如果是这样,你需要:

  1. 不使用会话 - 或 -
  2. 呼叫session_write_close开始下载,以释放会话锁之前。

请注意,调用session_write_close后会话的任何更改都将丢失。

+0

Ijust将Transfer类保存在Transfer.php文件中。而访问者通过http://127.0.0.1/Transfer.php,我不会在这里使用session。 – 2012-02-17 02:33:56