本人最近对workerMan很感兴趣,打算自己写一个和webman差不多的框架
(当然不是造轮子,只支持HTTP、HTTPS协议)
已经完成了90%,但是当我测试上传时一直行不通,总是进度在90%停住了,差200B但是查看保存的文件都正常
翻了翻WorkerMan源码,说实在的API太多本人没看明白,所以只能拜托作者了
恳请作者帮小白解惑
我写的相关源码:
elseif(substr($this->getrHeader('content-type'),0,19) == 'multipart/form-data'){
$split = '--'.\substr($this->getrHeader('content-type'),
strpos($this->getrHeader('content-type'),'boundary=') + 9
);// 读取分界符
if($split.PHP_EOL != ($f = fgets($this->socket))) {
echo "[ ERR ] POST出错:分界符不符合!原分界符:$split,传递的分界符:$f\n";
$this->filter(400,'POST BOUNDARY DOES NOT MATCH!');
return;
}
$len = strlen($f); // 统计最终数据
// 保存文件到缓冲区
$tmp = sys_get_temp_dir(); // 使用系统暂存区,可以更改
$maxLen = (int)$this->getrHeader('content-length');// 最终数据大小
if(!_q) echo "\n开始接收POST文件 总大小:$maxLen\n";
$start = time();
if(!_q) $proc = new cliProcess();
for ($i = 0 ; $i < 8 ; $i ++) { // 最大允许同时上传8个文件
if($len >= $maxLen) break;
$tmp = $this->parserHeader(false);// 由于文件信息与请求头很像所有直接调用
$len += $tmp['_length']; // 这里卡了很久,忘记这些头也有长度
$file = \fopen( // 打开文件,其实说实在的保存到RAM也一样
$tmp['savePath'] = \md5(\rand(10,1000)) // 随机文件名
,'w');
$data = '';
while(true) { // 未到分界处
$data = \fgets($this->socket); // 每次读取32K数据
$len += strlen($data); // 统计读取的数据
if($split.PHP_EOL == $data) break;
fwrite($file,$data); // 循环写到文件
if(!_q) $proc->set($len/$maxLen);// 设置进度条,这会消耗CPU,不过很少用到
}
fclose($file);
// 到了分界处,保存文件
array_push($this->file,$tmp); // 保存到files
}
echo "\n接收完毕,总文件数$i,耗时".time() - $start." MS\n";
}
/**
* 解析当前请求的请求头,如第一个参数是false将不保存到缓存
*
* @param ?bool $save
*/
public function parserHeader(bool $save = true):array {
$tmp = ['parsed'=>true];
$len = 0;
while(true) {
if(($str = fgets($this->socket)) == PHP_EOL) break;
$len += strlen($len);
$str = trim($str);
@list($name,$value) = \explode(':',$str,2);
$tmp [ \strtolower($name) ] = trim($value);
}
$tmp['_length'] = $len;
if($save === true) $this->requestHeader = $tmp;
return $tmp;
}
根据手册 https://www.php.net/manual/zh/function.fgets.php
最好不用fgets读取文件数据,fgets是获取一行数据,一行数据是以换行符为边界。如果文件最后一个字符不是换行符,fgets获取最后一段文件数据时就会卡住,直到连接断开才能返回
那请问该怎么实现上传呢?
不管是get post 还是上传,都是读取socket数据,数据读取上没有区别。主要是解析http协议内容
http上传rfc文档 https://www.ietf.org/rfc/rfc1867.txt
最简单的方法,抓一个上传的http报文,参考协议格式从报文里截取文件内容就行了。
怎么没有“点赞”功能?