urlencode仅限URL的目录和文件名

Tro*_*ott 11 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()需要像路径一样需要它的部分.然后,我会使用重新组合URL http_build_url().

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

Tro*_*ott 17

@deceze绝对让我走上了正确的道路,所以请回答他的回答.但这正是有效的:

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

有几点需要注意:

  • http_build_url需要PECL安装,所以如果你要将代码分发给其他人(就像我在这种情况下),你可能想要避免它并坚持使用reg exp解析,就像我在这里做的那样(从@ deceze的答案中大量窃取 - 再次,去吧upvote那件事).

  • urlencode()不是要走的路!您需要rawurlencode()路径以便空间被编码为%20和不被编码+.将空格编码+为查询字符串,但对路径不太热.

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


dec*_*eze 15

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

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

或者可能:

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

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