В LINUX есть очень специфическая утилита/инструмент сжатия по адресу /usr/bin/xz.
Теперь я использую Windows 10 x64 с PHP 8.1, и у меня есть библиотека php, которая в одной строке своего кода вызывает этот очень специфический файл LINUX (все остальное в этом коде совместимо с Windows, за исключением этой строки кода) с некоторые конкретные переключатели, задающие его параметры. Это строка:
$x = proc_open("/usr/bin/xz '--format=raw' '--lzma1=lc=3,lp=0,pb=2,dict=128KiB' '-c' '-'", [0 => ["pipe", "r"], 1 => ["pipe", "w"]], $p);
Я пытаюсь найти какую-нибудь утилиту, эквивалентную Windows, которую я мог бы заменить этой утилитой LINUX, которая принимала бы некоторые аналогичные переключатели для установки своих атрибутов, формулировки могут быть другими - это не было бы проблемой, я бы просто изменил их соответствующим образом.
Я думал, что Windows XZ Utils может быть именно таким, но, к сожалению, их xz.exe не принимает никаких переключателей, которые бы устанавливали его атрибуты, как это делает файл LINUX.
Есть ли какое-нибудь приложение для Windows (или, может быть, даже PHP-скрипт?), которое могло бы выполнять сжатие данных lzma1, аналогичное LINUX /usr/bin/xz, которое я мог бы использовать под Windows?
О, это интересная находка, спасибо. Но почему это просто не работает в PHP? Или я говорю это по-другому: не могли бы вы опубликовать точную строку, которую вы сейчас использовали с двоичным файлом Windows, пожалуйста? + файлы из какой именно папки вы использовали (в zip-файле несколько папок с разными версиями)? Я использовал те, что для x64.
@ChrisHaas, не могли бы вы также загрузить исходный пример сценария отсюда jan.fecik.sk/files/… подставьте туда эту строку для вашей версии Windows и скажите мне, каково значение переменной $o (строка 26)? Потому что мой по-прежнему ПУСТОЙ, но, я думаю, там должна быть довольно длинная строка букв и цифр.
@ChrisHaas относительно вашего принятого ответа - теперь у меня есть проблема: я пытаюсь создать ОТНОСИТЕЛЬНЫЙ ПУТЬ к xz.exe вместо АБСОЛЮТНОГО ПУТИ, который может создать проблемы после развертывания на работающем сервере. По какой-то причине это не работает: если я проверю существование xz.exe с помощью if (file_exists("xz.exe")), все пройдет нормально, но как только я заменю ваш абсолютный путь на $xz = "xz.exe"; или $xz = "xz"; это не работает. Можете ли вы посоветовать мне, как это решить, пожалуйста?
Во-первых, обычно лучше прикреплять комментарии к самому ответу, а не к исходному вопросу, так как другим будет сложно его прочитать. К вашему комментарию, гораздо проще отлаживать абсолютный путь вместо относительного пути, и тем более, чем «нет пути», которым является просто «xy.exe». Ваше мнение о том, что такое относительный/отсутствующий путь, часто не совпадает с тем, что думает PHP. Вот почему мы используем такие вещи, как __DIR__ и dirname(), чтобы построить абсолютный путь относительно. Значит xz.exe будет жить в той же папке, что и скрипт, тогда мой код будет портативным. Будет ли он жить относительно, попробуйте добавить dirname
Простое объяснение: изначально у меня был этот вопрос под вашим постом, НО я подумал, что что-то не так, потому что ответа не было несколько часов, затем я удалил его и разместил здесь, и вуаля, вы ответили. :-) Вот и все, еще раз извините. Меня беспокоит то, что когда __DIR__ вызывается из сценария на реальном сервере, если это не нарушает какие-то ограничения пути к серверу - извините, я не профессионал, поэтому мои вопросы могут показаться профессионалам глупыми (я пытаюсь понять все об этом еще).
Константа __DIR__ — это «Каталог файла. Если она используется внутри включения, возвращается каталог включаемого файла». Это гарантированно работает везде. Если у учетной записи пользователя нет разрешения на доступ к чему-либо, абсолютное и относительное ничего не исправит.
Я спрашивал, нельзя ли использовать просто ./xz.exe без полного пути? Требуется ли для этого .exe указание полного пути?
Мой лучший ответ — «может быть». Когда вы используете ./xz.exe, это не относительно текущего каталога (cd), а относительно текущего рабочего каталога (cwd). Часто/иногда cd и cwd совпадают, но это не гарантия. Однако показанная мной версия всегда создает абсолютный путь относительно компакт-диска. Лично я бы просто рекомендовал попробовать использовать __DIR__ на вашем реальном сервере, чтобы развеять любые опасения. Именно так работает практически каждая система, которую я построил и с которой столкнулся.
Хорошо, Крис, я попробую это сделать, как только веб-страница будет полностью готова на работающем сервере, надеюсь, что все будет хорошо, поскольку у меня нет опыта в подобных вещах. И только одно замечание, которое приходит мне на ум прямо сейчас: может ли быть на рабочем сервере какая-то проблема с вызовом .exe-файла из сценария (все будет размещено рядом точно так же, как в вашем примере - теперь это работает на моем тестовый сервер, это .exe рядом с .php)?
Да, вполне возможно, что учетная запись пользователя, под которой работает PHP, не будет иметь разрешения на запуск исполняемого файла. Эту проблему необходимо будет решить с помощью системы разрешений ОС. Но сначала попробуйте, прежде чем погружаться в это слишком глубоко. В PHP также есть функция, с помощью которой вы можете отключить основные функции в php.ini, а по соображениям безопасности/производительности [некоторые хосты отключают proc_open и другие исполняемые функции. Если вы получаете «вызов неопределенной функции», возможно, это причина. Но еще раз, просто попробуйте.






Вот моя версия вашего кода, надеюсь, комментарии добавят ясности.
Во-первых, я не скачивал запрошенный вами файл, я использовал файл отсюда: https://tukaani.org/xz/old.html#_windows
Во-вторых, моя версия предполагает, что PHP-скрипт и файл xz.exe находятся в одной папке. Если у вас это не так, сначала попробуйте мою версию, а затем попытайтесь выяснить, как изменить путь.
В-третьих, моя версия тестировалась только в CLI, у меня нет возможности запускать PHP на моем компьютере с Windows (кроме как через WSL).
В-четвертых, этот код записывает некоторый образец текста в стандартный ввод и сжимает его, и в случае успеха он выводит двоичный текст (который бесполезен, но показывает, что он работает). Обычно вы сохраняете это на диск, в кодировке Base64 или что-то еще.
<?php
// Variable for the current directory
$dir = __DIR__;
// Absolute path to the binary. This code assumes that it is in the
// same folder as this PHP script.
$xz = $dir . DIRECTORY_SEPARATOR . 'xz';
// Pipes to read/write to
$descriptorspec = [
0 => ["pipe", "r"],
1 => ["pipe", "w"],
2 => ["pipe", "w"],
];
// Open the process. Use the array format so that automatic
// escaping is handled for you.
$process = proc_open(
[
$xz,
'--format=raw',
'--lzma1=lc=3,lp=0,pb=2,dict=128KiB',
'-c',
'-',
],
$descriptorspec,
$pipes
);
// Make sure the above worked
if (!$process){
throw new RuntimeException('Could not open proc');
}
// Write some text to the stream to compress. You could also use
// file_get_contents or one of the command line switches
fwrite($pipes[0], 'This is a test');
// We're done writing
fclose($pipes[0]);
// Grab the contents of stdout and stderr
$output = stream_get_contents($pipes[1]);
$error = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
// Clean up
if (!$return_value = proc_close($process)){
// Successfully ran the command, do something with $output
echo 'Output:', PHP_EOL, $output;
}else{
echo 'There was an error, the command returned: ' . $return_value;
echo PHP_EOL;
echo $error;
}
Я только что скачал двоичный файл Windows. Хотя на странице
--helpэтого не показано, насколько я могу судить, все переключатели, которые вы указали, сработали. При тестировании пропустите PHP. Начните с того, чтобы заставить это работать в Windows CLI в целом. Как только это заработает, переключитесь на PHP.