我正在尝试直接从php://input
流解压缩zip文件。我正在运行Laravel Homestead,PHP 7.1.3-3+deb.sury.org~xenial+1
,端点位于myproject.app/upload
,这是curl
命令:
curl --request POST \
--url 'http://myproject.app/upload' \
--data-binary "@myfile.zip" \
以下列出了我尝试过的所有方法,但都失败了:
dd(file_get_contents('compress.zlib://php://input'));
file_get_contents():无法将输入类型的流表示为文件描述符
$fh = fopen('php://input', 'rb');
stream_filter_append($fh, 'zlib.inflate', STREAM_FILTER_READ, array('window'=>15));
$data = '';
while (!feof($fh)) {
$data .= fread($fh, 8192);
}
dd($data);
“”
$zip = new ZipArchive;
$zip->open('php://input');
$zip->extractTo(storage_path() . '/' . 'myfile');
$zip->close();
ZipArchive :: extractTo():无效或未初始化的Zip对象
以下是我在该主题上找到的所有链接:
http://php.net/manual/en/wrappers.php#83220
http://php.net/manual/en/wrappers.php#109657
http://php.net/manual/en/wrappers.compression.php#118461
https://secure.phabricator.com/rP42566379dc3c4fd01a73067215da4a7ca18f9c17
https://arjunphp.com/how-to-unpack-a-zip-file-using-php/
我开始认为使用PHP的内置zip功能在流上操作是不可能的。编写临时文件的开销和复杂性将非常令人失望。有谁知道怎么做,或者它是一个错误?
答案 0 :(得分:3)
经过更多的研究,我发现了答案,但并不令人满意。由于现代世界的一大错误, gzip和zip格式不一样。 gzip对单个文件进行编码(这就是我们经常看到tar.gz的原因),而zip则对文件和文件夹进行编码。我试图上传一个zip文件并用gzip解码它,这是行不通的。更多信息:
https://stackoverflow.com/a/20765054/539149
https://stackoverflow.com/a/1579506/539149
此问题的另一部分是 PHP忽略了为gzip提供流过滤器:
https://stackoverflow.com/a/11926679/539149
即使gzopen('php://temp', 'rb')
有效,gzopen('php://input', 'rb')
也不会,因为输入流不可重绕。这使得无法对内存中的流进行操作,因为无法将数据写入流,然后在与该流的单独gzip连接上读取解压缩的数据。这意味着以下代码不工作:
$input = fopen("php://input", "rb");
$temp = fopen("php://temp", "rb+");
stream_copy_to_stream($input, $temp);
rewind($temp);
dd(stream_get_contents(gzopen('php://temp', 'rb')));
人们已尝试过各种变通方法,但它们都有点摆弄:
http://php.net/manual/en/function.gzopen.php#105676
http://php.net/manual/en/function.gzdecode.php#112200
我确实设法获得了一个纯粹的内存解决方案,但由于无法使用流,因此会发生不必要的复制:
// works (stream + string)
dd(gzdecode(file_get_contents('php://input')));
// works (stream + file)
dd(stream_get_contents(gzopen(storage_path() . '/' . 'myfile.gz', 'rb')));
// works (stream + file)
dd(file_get_contents('compress.zlib://' . storage_path() . '/' . 'myfile.gz'));
// doesn't work (stream)
dd(stream_get_contents(gzopen('php://input', 'rb')));
// doesn't work (stream + filter)
dd(file_get_contents('compress.zlib://php://input'));
如果没有一个工作示例,我必须假设 PHP的zip实现不完整,因为它无法在流上运行。如果有人有更多信息,我很乐意再次访问。请发布任何通过流实现压缩上传/下载的示例或存储库,谢谢!