Como escaping do url para fopen

Parece que o fopen não pode abrir arquivos com espaços. Por exemplo:

$url = 'http://gatewaypeople.com/images/articles/cntrbutnssttmnts12_main 616x200.jpg'; fopen($url, 'r'); 

retorna falso (mente o espaço na url), mas o arquivo é acessível por navegadores. Eu também tentei escaping da url por urlencode e rawurlencode sem sorte. Como escaping corretamente dos espaços?

Você pode usar este código:

 $arr = parse_url ( 'http://gatewaypeople.com/images/articles/cntrbutnssttmnts12_main 616x200.jpg' ); $parts = explode ( '/', $arr['path'] ); $fname = $parts[count($parts)-1]; unset($parts[count($parts)-1]); $url = $arr['scheme'] . '://' . $arr['host'] . join('/', $parts) . '/' . urlencode ( $fname ); var_dump( $url ); 

Resposta alternativa e mais curta (obrigado a @Dziamid)

 $url = 'http://gatewaypeople.com/images/articles/cntrbutnssttmnts12_main 616x200.jpg'; $parts = pathinfo($url); $url = $parts['dirname'] . '/' . urlencode($parts['basename']); var_dump( $url ); 

SAÍDA:

 string(76) "http://gatewaypeople.com/images/articles/cntrbutnssttmnts12_main+616x200.jpg" 

rawurlencode é o caminho a seguir, mas não escape o URL completo. Apenas escaping do nome do arquivo. Então você vai acabar em http://gatewaypeople.com/images/articles/cntrbutnssttmnts12_main%20616x200.jpg

Todas as soluções propostas aqui são erradas porque elas não escapam da parte da string de consulta e da parte do diretório base. Além disso, eles não levam em consideração o usuário, passam e fragmentam partes do url.

Para escaping corretamente de um URL válido, você deve escaping separadamente das partes do caminho e das peças da consulta. Então, a solução é extrair as partes do url, escaping de cada parte e reconstruir a url.

Aqui está um snippet de código simples:

 function safeUrlEncode( $url ) { $urlParts = parse_url($url); $urlParts['path'] = safeUrlEncodePath( $urlParts['path'] ); $urlParts['query'] = safeUrlEncodeQuery( $urlParts['query'] ); return http_build_url($urlParts); } function safeUrlEncodePath( $path ) { if( strlen( $path ) == 0 || strpos($path, "/") === false ){ return ""; } $pathParts = explode( "/" , $path ); return implode( "/", $pathParts ); } function safeUrlEncodeQuery( $query ) { $queryParts = array(); parse_str($query, $queryParts); $queryParts = urlEncodeArrayElementsRecursively( $queryParts ); return http_build_query( $queryParts ); } function urlEncodeArrayElementsRecursively( $array ){ if( ! is_array( $array ) ) { return urlencode( $array ); } else { foreach( $array as $arrayKey => $arrayValue ){ $array[ $arrayKey ] = urlEncodeArrayElementsRecursively( $arrayValue ); } } return $array; } 

O uso seria simplesmente:

 $encodedUrl = safeUrlEncode( $originalUrl ); 

Nota lateral No meu trecho de código, estou fazendo uso do http://php.net/manual/it/function.http-build-url.php que está disponível na extensão PECL. Se você não tem extensão PECL em seu servidor, você simplesmente pode include a implementação pura do PHP: http://fuelforthefire.ca/free/php/http_build_url/

Felicidades 🙂

 $url = 'http://gatewaypeople.com/images/articles/cntrbutnssttmnts12_main 616x200.jpg'; fopen(urlencode($url), 'r');