2011-02-01 32 views
9

Tengo problemas que codifica una URL a un URI:URL para codificación URI cambia un "% 3D" a "% 253D"

mUrl = "A string url that needs to be encoded for use in a new HttpGet()"; 
URL url = new URL(mUrl); 
URI uri = new URI(url.getProtocol(), url.getAuthority(), url.getPath(), 
    url.getQuery(), null); 

Esto no hace lo que espero para el siguiente URL:

traspaso en el encordado:

http://m.bloomingdales.com/img?url=http%3A%2F%2Fimages.bloomingdales.com%2Fis%2Fimage%2FBLM%2Fproducts%2F3%2Foptimized%2F1140443_fpx.tif%3Fwid%3D52%26qlt%3D90%2C0%26layer%3Dcomp%26op_sharpen%3D0%26resMode%3Dsharp2%26op_usm%3D0.7%2C1.0%2C0.5%2C0%26fmt%3Djpeg&ttl=30d

resulta:

http://m.bloomingdales.com/img?url=http%253A%252F%252Fimages.bloomingdales.com%252Fis%252Fimage%252FBLM%252Fproducts%252F3%252Foptimized%252F1140443_fpx.tif%253Fwid%253D52%2526qlt%253D90%252C0%2526layer%253Dcomp%2526op_sharpen%253D0%2526resMode%253Dsharp2%2526op_usm%253D0.7%252C1.0%252C0.5%252C0%2526fmt%253Djpeg&ttl=30d

que se rompe. Por ejemplo, el %3D se convierte en %253D Parece que está haciendo algo misterioso para los% que ya están en la cadena.

¿Qué está pasando y qué estoy haciendo mal aquí?

Respuesta

22

Usted está poniendo en primer lugar la (ya se escape) cadena en la clase URL. Eso no escapa nada. Luego está sacando secciones del URL, que las devuelve sin ningún procesamiento posterior (por lo tanto, aún se han escapado porque se habían escapado cuando las insertó). Finalmente, está colocando las secciones en la clase URI, usando el multi-argument constructor. Este constructor se especifica como codificación de los componentes de URI usando porcentajes.

Por lo tanto, es en este paso final que, por ejemplo, ":" se convierte en "%3A" (bueno) y "%3A" se convierte en "%253A" (malo). Dado que está colocando URL que ya están codificadas *, no desea volver a codificarlas. Por favor, el single-argument constructor de URI es tu amigo. No escapa a nada, y requiere que pase una cadena antes de escapar. Por lo tanto, no es necesario en absoluto URL:

mUrl = "A string url is already percent-encoded for use in a new HttpGet()"; 
URI uri = new URI(mUrl); 

* El único problema es que si sus URL a veces no son codificados por ciento, ya veces son. Entonces tienes un problema mayor. Debe decidir si su programa está comenzando con una URL que siempre está codificada, o una que necesita ser codificada.

Tenga en cuenta que no existe tal cosa como una URL completa que no está codificada en porcentajes. Por ejemplo, no puede tomar la URL completa "http://example.com/bob&co" y de alguna manera convertirla en la URL codificada correctamente "http://example.com/bob%26co": ¿cómo puede saber la diferencia entre la sintaxis (que no se debe escapar) y los caracteres (que debería)? Esta es la razón por la que la forma de argumento único de URI requiere que las cadenas ya estén escapadas. Si usted tiene cadenas sin escape, es necesario que ellos por ciento a codificar antes de insertarlos en la sintaxis URL completa, y eso es lo que el constructor de múltiples argumento de URI le ayuda a hacerlo.

Edit: Eché de menos el hecho de que el código original descarta el fragmento.Si desea eliminar el fragmento (o cualquier otra parte) de la URL, puede construir el URI como se indicó anteriormente, luego extraer todas las partes según sea necesario (serán decodificadas en cadenas normales), y luego volver a pasarlas a el constructor URI multi-argumento (donde estarán re-codificada como componentes URI):

uri = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), 
       uri.getPath(), uri.getQuery(), null) // Remove fragment 
+0

Eso tiene sentido, gracias por la redacción. Las URL se extraen del código html, así que supongo que tendrían que estar codificadas entonces? Una de las razones por las que estaba usando el URL y el constructor de argumentos múltiples fue porque necesitaba eliminar el fragmento (si lo hubiera) del URI. ¿Hay alguna manera de que pueda hacer esto sin forzar la doble codificación? Algo como String urlMinusFragment = url.getProtocol() + ": //" + url.getAuthority() + url.getPath() + "?" + url.getQuery(); ¿Estás seguro de hacer? Entonces podría lanzar esa cadena en el nuevo constructor de URI (cadena). Gracias de nuevo. – cottonBallPaws

+0

Si está extrayendo URL de, por ejemplo, la propiedad 'href' en HTML, entonces siempre deben codificarse correctamente (si no lo están, el HTML no es válido, por lo que podría tratarlo como un error). La técnica para eliminar el fragmento parece correcta, pero está construyendo manualmente una URL (para la cual hay una biblioteca). Usaría la clase URI. Al igual que la URL, URI tiene captadores de componentes, pero devuelve cadenas * decodificadas * que son seguras para volver a colocar en el URI. Así 'URI (uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(), uri.getQuery(), null)' debería funcionar. – mgiuca

+0

brillant, funciona a la perfección. Gracias – cottonBallPaws

4

El URL clase no decodificar los -sequences% cuando se analiza la URL, pero la clase URI ellas es la codificación (de nuevo). Use URI para analizar la cadena de URL.

Javadocs:

http://download.oracle.com/javase/6/docs/api/java/net/URL.html

La clase URL no en sí codificar o descodificar cualquiera de los componentes de URL de acuerdo con el mecanismo de escape definido en RFC2396. Es responsabilidad del llamante codificar los campos, que deben escaparse antes de llamar a la URL, y también decodificar cualquier campo escapado, que se devuelve desde la URL. Además, dado que la URL no tiene conocimiento del escape de URL, no reconoce la equivalencia entre la forma codificada o descodificada de la misma URL. Por ejemplo, las dos direcciones URL:

http://foo.com/hello world/ and http://foo.com/hello%20world 

serían considerados no iguales entre sí. Nota: la clase URI realiza escapes de sus campos de componentes en ciertas circunstancias.

La forma recomendada para gestionar la codificación y decodificación de direcciones URL es utilizar URI, y para convertir entre estas dos clases usando Touri() y URI.toURL().

-2

Lo que ocurre aquí es que el % signos de la primera URL se escaparon, lo que significa que se convierten en %25 en la salida. Debe poner precauciones en su lugar para que su script escape caracteres alfanuméricos, así como algunos símbolos, pero no caracteres ya escapó.

Estos son algunos personajes que necesitan escapan:

< 
> 
" 
! 
# 
$ 
' 
(
) 
* 
, 
- 
. 
/
: 
; 
@ 
[ 
\ 
] 
^ 
_ 
` 
{ 
| 
} 
~ 

El resto, como =, % y & y caracteres alfanuméricos, no lo hacen.

+1

No, no es la forma correcta de pensarlo en absoluto. Ya tiene una URL completa con porcentaje de codificación. Cada personaje que ya necesita ser codificado está codificado. Si su consejo es no codificar los signos "%", seguro, "% 3A" se mantendrá como "% 3A" en lugar de "% 253A", pero también estará sobrecodificando otros elementos sintácticos. Por ejemplo, "x = 4 & y = 7" (es decir, x es "4" e y es "7") se convertirá en "x = 4% 26y = 7" (lo que significa que x es "4 y y = 7"). Tratar de obtener el conjunto exacto de caracteres correcto significa que los casos más comunes funcionarán, y tendrás menos casos con bordes defectuosos, pero no los eliminarás. – mgiuca

+0

Además, ha enumerado "=" y "%" como ambos que necesitan escaparse, y que no necesitan escaparse. – mgiuca

+0

Gracias por señalar esos errores. Mi impresión de lo que estaba mal con el código de littleFluffyKitty era que algunos caracteres tenían doble codificación. – pop850

4

% 3d significa->=(igual)

A nd

% 253D ->=(Equal) 6HEX decimal (byte) 3D

% 253D indicador hexagonal para CGI: % 3D

+0

% 3d en formato UTF-8? ¿Cómo podemos decodificar String con caracteres% 3D,% 26 etc.? – Kushal