Разархивировать или раздуть входной поток php: //?

Пытаюсь распаковать zip-файл прямо из php://input потока. Я запускаю 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 (): не может представлять поток типа Input как дескриптор файла


$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. Накладные расходы и сложность записи временных файлов были бы довольно разочаровывающими. Кто-нибудь знает, как это сделать, или это баг?


person Zack Morris    schedule 08.07.2017    source источник
comment
Для этого используйте phar: //: stackoverflow.com/a/4878849/606859   -  person geek-merlin    schedule 05.09.2019


Ответы (1)


После дополнительных исследований я нашел ответ, но он не является удовлетворительным. Из-за одной из самых больших ошибок современного мира 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'));

Без рабочего примера я должен предположить, что реализация zip в PHP является неполной, потому что она не может работать с потоками. Если у кого-то есть дополнительная информация, я буду рад вернуться к этому. Пожалуйста, опубликуйте любые примеры или репозитории, которые реализуют заархивированные закачки / закачки через потоки, спасибо!

person Zack Morris    schedule 08.07.2017