正如其他答案所说:
- 你不能在记忆中拥有所有这些
- 解决方案是使用
CURLOPT_FILE
但是,您可能不想真正创建一个文件,您可能希望使用内存中的数据...只要它“到达”就使用它。
一种可能的解决方案可能是定义您自己的流包装器,并使用这个包装器,而不是一个真实的文件,CURLOPT_FILE
首先,请看:
现在,让我们举个例子。
首先,让我们创建我们的流包装类:
class MyStream {
protected $buffer;
function stream_open($path, $mode, $options, &$opened_path) {
// Has to be declared, it seems...
return true;
}
public function stream_write($data) {
// Extract the lines ; on y tests, data was 8192 bytes long ; never more
$lines = explode("\n", $data);
// The buffer contains the end of the last line from previous time
// => Is goes at the beginning of the first line we are getting this time
$lines[0] = $this->buffer . $lines[0];
// And the last line os only partial
// => save it for next time, and remove it from the list this time
$nb_lines = count($lines);
$this->buffer = $lines[$nb_lines-1];
unset($lines[$nb_lines-1]);
// Here, do your work with the lines you have in the buffer
var_dump($lines);
echo '<hr />';
return strlen($data);
}
}
我要做的是:
- 在数据块到达时处理它们(我使用 var_dump,但你会做通常的事情)
- 请注意,您不会得到“完整行”:行尾是块的开头,同一行的开头是前一个块的结尾,因此,您必须保留一些部分对
stream_write 的调用之间的一个块
接下来,我们注册这个流包装器,与伪协议“test”一起使用:
// Register the wrapper
stream_wrapper_register("test", "MyStream")
or die("Failed to register protocol");
而且,现在,我们执行 curl 请求,就像我们在写入“真实”文件时所做的那样,就像其他答案建议的那样:
// Open the "file"
$fp = fopen("test://MyTestVariableInMemory", "r+");
// Configuration of curl
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.rue89.com/");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 256);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FILE, $fp); // Data will be sent to our stream ;-)
curl_exec($ch);
curl_close($ch);
// Don't forget to close the "file" / stream
fclose($fp);
请注意,我们不使用真实文件,而是使用我们的伪协议。
这样,每次数据块到达时,MyStream::stream_write 方法将被调用,并且将能够处理少量数据(当我测试时,我总是得到 8192 字节,无论我使用什么值CURLOPT_BUFFERSIZE)
几点说明:
- 显然,你需要比我做更多的测试
- 如果行长于 8192 字节,我的 stream_write 实现可能无法正常工作;-)
- 这只是一些提示,而不是一个完全有效的解决方案:您必须(再次)测试,并且可能编写更多代码!
不过,我希望这会有所帮助 ;-)
玩得开心!