Implement parallel download

This commit is contained in:
Ivailo Hristov 2016-02-11 16:38:31 +02:00
parent b69fa7f2a9
commit 11a539bcbd

View File

@ -2064,39 +2064,70 @@ class SFTP extends SSH2
$start = $offset; $start = $offset;
$size = $this->max_sftp_packet < $length || $length < 0 ? $this->max_sftp_packet : $length; $size = $this->max_sftp_packet < $length || $length < 0 ? $this->max_sftp_packet : $length;
while (true) { $read = 0;
$packet = pack('Na*N3', strlen($handle), $handle, $offset / 4294967296, $offset, $size); $error = false;
if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet)) { while (!$error) {
if ($fclose_check) { $request_id_offset = 5;// just like that, a random number
fclose($fp); $i = $request_id_offset;
}
return false;
}
$response = $this->_get_sftp_packet(); // this puts a constraint on 32 bit systems where files larger than 4GB will not be completely downloaded if length is not specified.
switch ($this->packet_type) { $limit = $length > 0 ? max($this->max_sftp_packet, $length) : PHP_INT_MAX;
case NET_SFTP_DATA:
$temp = substr($response, 4); while ($i < NET_SFTP_QUEUE_SIZE+$request_id_offset && $read < $limit) {
$offset+= strlen($temp); $subtemp = $start + $read;
if ($local_file === false) { $possible_packet_sizes = array($this->max_sftp_packet, $size);
$content.= $temp; if ($limit - $read > 0) {
} else { $possible_packet_sizes[] = $limit - $read;
fputs($fp, $temp); }
}
break; $packet_size = min($possible_packet_sizes);
case NET_SFTP_STATUS:
// could, in theory, return false if !strlen($content) but we'll hold off for the time being $packet = pack('Na*N3', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, $packet_size);
$this->_logError($response); $this->request_id = $i;
break 2; if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet)) {
default:
if ($fclose_check) { if ($fclose_check) {
fclose($fp); fclose($fp);
} }
throw new \UnexpectedValueException('Expected SSH_FXP_DATA or SSH_FXP_STATUS'); return false;
}
$this->request_id=1;
$read += $packet_size;
$i++;
} }
if ($length > 0 && $length <= $offset - $start) { while ($i > $request_id_offset) {
break; $this->request_id = $i;
$response = $this->_get_sftp_packet();
$this->request_id=1;
switch ($this->packet_type) {
case NET_SFTP_DATA:
$temp = substr($response, 4);
$offset+= strlen($temp);
if ($local_file === false) {
$content.= $temp;
} else {
fputs($fp, $temp);
}
break;
case NET_SFTP_STATUS:
// could, in theory, return false if !strlen($content) but we'll hold off for the time being
$this->_logError($response);
// don't break out of the loop so we can read the remaining responses
$error = true;
break;
default:
if ($fclose_check) {
fclose($fp);
}
throw new \UnexpectedValueException('Expected SSH_FXP_DATA or SSH_FXP_STATUS');
}
if ($length > 0 && $length <= $offset - $start) {
// don't break out of the loop so we can read the remaining responses
$error = true;
}
$i--;
} }
} }