urlencode仅限URL的目录和文件名

时间:2011-11-01 22:35:27

标签: php urlencode

我需要使用PHP对URL的目录路径和文件名进行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。

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

5 个答案:

答案 0 :(得分:17)

@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而不是+。将空格编码为+对于查询字符串来说很好,但对路径来说不是那么热。

  • 这不适用于需要编码的用户名/密码的网址。对于我的用例,我不认为我关心那些,所以我并不担心。但是,如果您的用例在这方面有所不同,那么您需要注意这一点。

答案 1 :(得分:15)

正如你所说,沿着这些方向应该做的事情:

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

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

更简单:

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

答案 4 :(得分:-1)

我觉得这个功能还可以:

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