Urlencode только каталог и имена файлов URL-адреса
Мне нужно, чтобы URL-адрес кодировал только путь к каталогу и имя файла URL с помощью PHP.
Итак, я хочу кодировать что-то вроде http://example.com/file name
и получить результат http://example.com/file%20name
.
Конечно, если я делаю urlencode('http://example.com/file name');
, тогда я получаю http%3A%2F%2Fexample.com%2Ffile+name
.
Очевидным (для меня, в любом случае) решением является использование parse_url()
для разделения URL-адреса на схему, хост и т.д., а затем просто urlencode()
части, которые нуждаются в ней, как путь. Затем, я бы собрал URL-адрес, используя http_build_url()
.
Есть ли более элегантное решение? Или это в основном способ пойти?
Ответы
Ответ 1
@deceze определенно заставил меня спуститься по правильному пути, так что держите его ответ. Но вот что именно сработало:
$encoded_url = preg_replace_callback('#://([^/]+)/([^?]+)#', function ($match) {
return '://' . $match[1] . '/' . join('/', array_map('rawurlencode', explode('/', $match[2])));
}, $unencoded_url);
Можно отметить несколько вещей:
-
http_build_url требует установки PECL, поэтому, если вы распространяете свой код другим (как и я в этом случае), вам может потребоваться его избежать и придерживаться анализатора reg exp, как я это сделал (сильно воровство от @deceze ответ - опять же, идите вверх по этой вещи).
-
urlencode()
- это не путь! Вам нужно rawurlencode()
для пути, чтобы пробелы были закодированы как %20
, а не +
. Кодирование пробелов как +
отлично подходит для строк запроса, но не так горячо для путей.
-
Это не будет работать для URL-адресов, для которых требуется имя пользователя/пароль. Для моего случая использования я не думаю, что меня это волнует, поэтому я не волнуюсь. Но если ваш вариант использования отличается в этом отношении, вам нужно позаботиться об этом.
Ответ 2
Как вы говорите, что-то в этом направлении должно это сделать:
$parts = parse_url($url);
if (!empty($parts['path'])) {
$parts['path'] = join('/', array_map('rawurlencode', explode('/', $parts['path'])));
}
$url = http_build_url($parts);
Или, возможно:
$url = preg_replace_callback('#https?://.+/([^?]+)#', function ($match) {
return join('/', array_map('rawurlencode', explode('/', $match[1])));
}, $url);
(Regex не полностью протестирован)
Ответ 3
function encode_uri($url){
$exp = "{[^0-9a-z_.!~*'();,/?:@&=+$#%\[\]-]}i";
return preg_replace_callback($exp, function($m){
return sprintf('%%%02X',ord($m[0]));
}, $url);
}
Ответ 4
Я думаю, что эта функция в порядке:
function newUrlEncode ($url) {
return str_replace(array('%3A', '%2F'), '/', urlencode($url));
}
Ответ 5
Гораздо проще:
$encoded = implode("/", array_map("rawurlencode", explode("/", $path)));