urlencode只有URL的目录和文件名

问题描述:

我需要使用PHP编码URL的目录路径和文件名。urlencode只有URL的目录和文件名

所以我想编码像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()这些部分就像路径一样。然后,我会使用http_build_url()重新组装URL。

有没有比这更优雅的解决方案?或者,这基本上是要走的路?

+0

这似乎是最可靠的解决方案给我。 – Herbert

+0

每个文档:urlencode用于URL的查询部分。 rawurlencode的路径,但一定要排除斜杠。 –

@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不起作用。对于我的用例,我不认为我在乎这些,所以我并不担心。但是,如果你的用例在这方面有所不同,那么你需要注意这一点。

+0

对,我忘了将完整的URL重新拼回去。我想我们可以改变正则表达式来做非捕捉后视,所以它只提取和修改路径。无论如何。 :) – deceze

正如你所说,这些方针的东西应该这样做:

$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); 

(正则表达式没有完全虽然测试)

+0

+1意识到如果路径中的斜线不会像你一样进行特殊处理,那么它们会将所有东西都弄乱。 – Trott

+0

不错。正则表达式确实需要进行一些调整,但它使我找到了正确的道路。 – Trott

+0

我会用'rawurlencode'替换'urlencode'。 – kayue

我觉得这个功能确定:

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

这适用于问题中的示例,但它不健壮。例如,如果在URL中指定端口,它将返回错误的结果。 – Trott

简单多了:

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

请解释您的答案,因为这是一个老问题,建议您告诉我们您的答案与已提供的答案不同。谢谢。 –

+0

这个答案是不正确的。它将编码遵循该方案的冒号。给定输入'http://example.com/file name',它会生成'http%3A // example.com/file%20name'。正确的结果是'http:// example.com/file%20name'。 – Trott

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