经测试使用curl -i --range 20-50
可以正常读取出该部分的数据
但是使用wget -c
就出现如下报错
Connecting to 192.168.1.224:8001... connected.
HTTP request sent, awaiting response... -1
2021-06-01 23:41:25 ERROR -1: Malformed status line.
Retrying.
跟踪执行过程有运行到send()
header 信息如下:
array(20) {
["QUERY_STRING"]=>
string(1049) "object_id=5000000038"
["REQUEST_METHOD"]=>
string(3) "GET"
["REQUEST_URI"]=>
string(1065) "/api/object/obi?object_id=5000000038"
["SERVER_PROTOCOL"]=>
string(8) "HTTP/1.1"
["SERVER_SOFTWARE"]=>
string(16) "workerman/3.5.31"
["SERVER_NAME"]=>
string(13) "192.168.1.224"
["HTTP_HOST"]=>
string(18) "192.168.1.224:8001"
["HTTP_USER_AGENT"]=>
string(21) "Wget/1.14 (linux-gnu)"
["HTTP_ACCEPT"]=>
string(3) "*/*"
["HTTP_ACCEPT_LANGUAGE"]=>
string(0) ""
["HTTP_ACCEPT_ENCODING"]=>
string(0) ""
["HTTP_COOKIE"]=>
string(0) ""
["HTTP_CONNECTION"]=>
string(10) "Keep-Alive"
["CONTENT_TYPE"]=>
string(0) ""
["REMOTE_ADDR"]=>
string(13) "192.168.1.225"
["REMOTE_PORT"]=>
int(43526)
["REQUEST_TIME"]=>
int(1622605285)
["REQUEST_TIME_FLOAT"]=>
float(1622605285.0338)
["HTTP_RANGE"]=>
string(15) "bytes=40257712-"
["SERVER_PORT"]=>
string(4) "8001"
}
string(471) "HTTP /1.1 206 Partial Content
Accenpt-Ranges: bytes
Content-Length: 65227761
Content-Range: bytes 40257712-105485472/105485473
Content-Type: application/octet-stream
Cache-Control: public
Pragma: public
Etag: 3c7358115ae8e7bef4c3c79e0906cfc4b360a4bffa11bdb28aa2dce4f89b00df
Content-Disposition:attachment; filename=3c7358115ae8e7bef4c3c79e0906cfc4b360a4bffa11bdb28aa2dce4f89b00df
Connection: keep-alive
Last-Modified: Tue, 01 Jun 2021 14:44:28 Asia/Shanghai
"
这里是代码:
protected function sendFile($connection, $filePath)
{
$fileinfo = \pathinfo($filePath);
$filename = isset($fileinfo['filename']) ? $fileinfo['filename'] : '';
$filesize = \filesize($filePath);
$start = 0;
$contentLength = $filesize;
$info = \stat($filePath);
$modified_time = $info ? \date('D, d M Y H:i:s', $info['mtime']) . ' ' . \date_default_timezone_get() : '';
if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $info) {
// Http 304.
if ($modified_time === $_SERVER['HTTP_IF_MODIFIED_SINCE']) {
// 304
Http::header('HTTP/1.1 304 Not Modified');
// Send nothing but http headers..
if (\strtolower($_SERVER['HTTP_CONNECTION']) === "keep-alive") {
$connection->send('');
} else {
$connection->close('');
}
return;
}
}
if ($modified_time) {
$modified_time = "Last-Modified: $modified_time\r\n";
}
if(isset($_SERVER['HTTP_RANGE']) && !empty($_SERVER['HTTP_RANGE'])) {
[, $range] = explode('=', $_SERVER['HTTP_RANGE'], 2);
[$start, $end] = explode('-', $range);
$end = $end ?: $filesize - 1;
$contentLength = $end - $start + 1;
$header = "HTTP /1.1 206 Partial Content\r\n";
$header .= "Accenpt-Ranges: bytes\r\n";
$header .= "Content-Length: ${contentLength}\r\n";
$header .= "Content-Range: bytes ${start}-${end}/${filesize}\r\n";
} else {
$header = "HTTP/1.1 200 OK\r\n";
$header .= "Content-Length: ${contentLength}\r\n";
// $header .= "Content-Range: bytes 0-${end}/${filesize}\r\n";
}
$header .= "Content-Type: application/octet-stream\r\n";
$header .= "Cache-Control: public\r\n";
$header .= "Pragma: public\r\n";
$header .= "Etag: ${filename}\r\n";
$header .= "Content-Disposition:attachment; filename=${filename}\r\n";
$header .= "Connection: keep-alive\r\n";
$header .= $modified_time;
$header .= "\r\n";
$connection->send($header, true);
// Read file content from disk piece by piece and send to client.
$connection->fileHandler = \fopen($filePath, 'r');
\fseek($connection->fileHandler, $start);
$do_write = function() use ($connection, $contentLength) {
// Send buffer not full.
$stepLength = 8192;
while(empty($connection->bufferFull)) {
$readCount = $contentLength > $stepLength ? $stepLength : $contentLength;
$contentLength -= $readCount;
// Read from disk.
$buffer = \fread($connection->fileHandler, $readCount);
// Read eof.
if($buffer === '' || $buffer === false) {
return;
}
if ($contentLength === 0) {
$connection->close($buffer, true);
return;
} else {
$connection->send($buffer, true);
}
}
};
// Send buffer full.
$connection->onBufferFull = function($connection) {
$connection->bufferFull = true;
};
// Send buffer drain.
$connection->onBufferDrain = function($connection) use ($do_write) {
$connection->bufferFull = false;
$do_write();
};
$do_write();
}