2011-11-01 8 views
11

Potrzebuję adresu URL koduj tylko ścieżkę do katalogu i nazwę pliku URL używając PHP.urlencode tylko katalog i nazwy plików adresu URL

Tak więc chcę zakodować coś w rodzaju http://example.com/file name i mieć wynik w postaci http://example.com/file%20name.

Oczywiście, jeśli zrobię urlencode('http://example.com/file name');, to skończę z http%3A%2F%2Fexample.com%2Ffile+name.

Oczywistym (dla mnie, tak) rozwiązaniem jest użycie parse_url(), aby podzielić adres URL na schemat, host itp., A następnie po prostu urlencode() części, które potrzebują go tak jak ścieżka. Następnie ponownie złożyć URL za pomocą http_build_url().

Czy istnieje bardziej eleganckie rozwiązanie? Czy jest to w zasadzie droga do zrobienia?

+0

który wydaje się jak najbardziej niezawodne rozwiązanie dla mnie. – Herbert

+0

Zgodnie z dokumentacją: kod urlencode jest dla części kwerendy adresu URL. rawurlencode dla ścieżki, ale upewnij się, że wykluczasz ukośniki. –

Odpowiedz

15

@deceze zdecydowanie got me going na właściwej ścieżce, więc przejdź do jego odpowiedzi. Ale tutaj jest dokładnie to, co zadziałało:

$encoded_url = preg_replace_callback('#://([^/]+)/([^?]+)#', function ($match) { 
       return '://' . $match[1] . '/' . join('/', array_map('rawurlencode', explode('/', $match[2]))); 
      }, $unencoded_url); 

Istnieje kilka rzeczy do uwaga:

  • http_build_url wymaga PECL zainstalować więc jeśli się dystrybucją kodu do innych (jak jestem w tym przypadku) możesz chcieć tego uniknąć i trzymać się reg exp parsing tak jak ja tutaj (kradnąc ciężko z odpowiedzi @ deceze - znowu, idź upwrote to coś).

  • urlencode() to nie jest droga! Do ścieżki należy użyć rawurlencode(), aby spacje były kodowane jako %20, a nie +. Kodowanie spacji jako + jest w porządku dla ciągów zapytań, ale nie tak gorące dla ścieżek.

  • Nie będzie działać dla adresów URL, które wymagają zakodowania nazwy użytkownika/hasła. Dla mojego przypadku użycia, nie wydaje mi się, żebym się tym przejmował, więc nie martwię się. Ale jeśli twój przypadek użycia jest inny pod tym względem, musisz się tym zająć.

+0

W porządku, zapomniałem ponownie połączyć cały URL. Sądzę, że można zmienić wyrażenie regularne, aby wykonać przechwytywanie bez przechwytywania, więc tylko wyodrębnia i modyfikuje ścieżkę. +1 i tak. :) – deceze

14

jak mówisz, coś wzdłuż tych linii powinna zrobić:

$parts = parse_url($url); 
if (!empty($parts['path'])) { 
    $parts['path'] = join('/', array_map('rawurlencode', explode('/', $parts['path']))); 
} 
$url = http_build_url($parts); 

ewentualnie:

$url = preg_replace_callback('#https?://.+/([^?]+)#', function ($match) { 
      return join('/', array_map('rawurlencode', explode('/', $match[1]))); 
     }, $url); 

(Regex nie w pełni przetestowane choć)

+0

+1 za zrozumienie, że ukośniki na ścieżce zepsują wszystko, jeśli nie są traktowane tak jak Ty. – Trott

+0

Nice. Wyrażenie regularne wymaga pewnych poprawek, ale ustawiło właściwą ścieżkę. – Trott

+0

Zamieniłabym "urlencode" na 'rawurlencode'. – kayue

-1

myślę tę funkcję OK:

function newUrlEncode ($url) { 
    return str_replace(array('%3A', '%2F'), '/', urlencode($url)); 
} 
+0

Działa to na przykład w pytaniu, ale nie jest solidne. Na przykład zwraca błędny wynik, jeśli port jest podany w adresie URL. – Trott

-1

znacznie prostsze:

$encoded = implode("/", array_map("rawurlencode", explode("/", $path))); 
+1

proszę wyjaśnić swoją odpowiedź, ponieważ jest to stare pytanie, zaleca się, aby powiedzieć nam, jak twoja odpowiedź jest inna niż inne już dostarczone. Dziękuję Ci. –

+0

Ta odpowiedź jest niepoprawna. Będzie kodował dwukropek następujący po schemacie. Biorąc pod uwagę wejściową 'http://example.com/file name', tworzy ona' http% 3A // example.com/file% 20name'. Poprawny wynik to 'http: // example.com/file% 20name'. – Trott

1
function encode_uri($url){ 
    $exp = "{[^0-9a-z_.!~*'();,/?:@&=+$#%\[\]-]}i"; 
    return preg_replace_callback($exp, function($m){ 
     return sprintf('%%%02X',ord($m[0])); 
    }, $url); 
} 
Powiązane problemy