2012-11-12 2 views
1

일부 웹 사이트의 콘텐츠를 가져 오는 데 문제가 있습니다. 국제 문자가 포함 된 다른 URL로 리디렉션되는 url로 이동하려고하면 Java에서 일반적으로 404 오류가 발생합니다. 브라우저에서이 url을 따라 가면 올바른 데이터를 얻습니다.URL의 Java HttpUrlConnection 국제 문자가 재 연결됩니다.

내가 hXXp로 이동하려면 예를 들어 : //www.dandy-magazine : //shar.es/cISmv

브라우저 hXXp 올바르게 나를 리디렉션 (2 개 이상의 유효한 링크를 게시 할 수 없습니다). com/la-griffe-de-la-tour-d % E2 % 80 % 99argent. wget에서 나는 처음에 사이트가 기존의 "위치 : http://www.dandy-magazine.com/la-griffe-de-la-tour-d%E2%80%99argent"

과 함께 리디렉션 301을 반환한다는 것을 알 수 있습니다. Java에서 (whith 리디렉션이 해제 된 경우) 리디렉션 301은 "Location: http://www.dandy-magazine.com/la-griffe-de-la-tour-dâargent"과 함께 반환됩니다. URL 인코딩은 다음과 같습니다. "http://www.dandy-magazine.com/la-griffe-de-la-tour-d%C3%A2%C2%80%C2%99argent". 보시다시피, 완전히 다른 사이트입니다.

샘플 코드는 (기본적으로 버전 1과 버전 2는 같은 일을 수행) : 도움

에 대한

// version 1 - let java handle redirects 
URL url = new URL("http://shar.es/cISmv"); 
HttpURLConnection con = (HttpURLConnection) url.openConnection(); 
con.setInstanceFollowRedirects(true); 
con.getResponseCode(); 
return con.getURL(); // returned url is not what it should be 

// version 2 - I want to handle redirects 
URL url = new URL("http://shar.es/cISmv"); 
HttpURLConnection con = (HttpURLConnection) url.openConnection(); 
con.setInstanceFollowRedirects(false); 
con.getResponseCode(); 
String loc = con.getHeaderField("Location"); 
// here is the problem, loc is not initialized with a correct url 
// returned String corresponds to url returned in version 1 

들으을

+0

올바른 문자 세트 인코딩을 사용하십시오. 게시 한 첫 번째 링크는 iso 8859-1에 인코딩되어 있고 두 번째 링크는 유니 코드로 인코딩되어있을 것입니다. – Twilite

+0

안녕하세요. 의견을 남기려면 쓰세요. 나는 그 질문을 약간 분명하게했다.기본적으로 내 문제는 자바와 웹 브라우저에서 동일한 사이트에 액세스하려고 할 때 다른 리다이렉션 결과를 얻는다는 것입니다. 나는이 문제가 문자 인코딩일지도 모른다고 생각했지만, 어떤 인코딩이 사용되었는지 어떻게 알 수 있습니까? 어떻게 설정합니까? – Caldur

답변

1

지금까지 그 값이 때 나는, 자바는 Location 헤더를 처리하지 않습니다 말할 수있는 UTF-8로 인코딩됩니다.

URL은 .../la-griffe-de-la-tour-dargent와 같아야합니다. 이전 문장에서는 ASCII 작은 따옴표 문자를 사용하고 있습니다. 대신 작은 따옴표 문자를 사용하지만 웹 사이트는 Wireshark를 추적 반환 된 위치 헤더 인코딩이 문자 UTF-8을 가지고 계시 유니 코드 문자

00002019 RIGHT SINGLE QUOTATION MARK 
Glyph: ’ 
UTF-8: E2 80 99 

을 사용하기로 결정했습니다.

00e0 65 70 2d 61 6c 69 76 65 0d 0a 4c 6f 63 61 74 69 ep-alive ..Locati 
00f0 6f 6e 3a 20 68 74 74 70 3a 2f 2f 77 77 77 2e 64 on: http ://www.d 
0100 61 6e 64 79 2d 6d 61 67 61 7a 69 6e 65 2e 63 6f andy-mag azine.co 
0110 6d 2f 6c 61 2d 67 72 69 66 66 65 2d 64 65 2d 6c m/la-gri ffe-de-l 
0120 61 2d 74 6f 75 72 2d 64 e2 80 99 61 72 67 65 6e a-tour-d ...argen 
0130 74 0d 0a 0d 0a 30 0d 0a 0d 0a      t....0.. ..  

나는 이것이 합법적 인 HTTP인지 잘 모릅니다. 이 문제에 대해서는 웹에서 분명히 많은 의문점이 있습니다. 그것이 합법적인지 여부에 관계없이 HttpURLConnection 클래스는 잘 처리하지 못합니다.

String loc = con.getHeaderField("Location"); 

에 대한 호출은 dargent 사이에 하나의 문자 (2019)가 있었다 문자열 http://www.dandy-magazine.com/la-griffe-de-la-tour-d’argent를 반환해야합니다. 대신 3 개의 UTF-8 바이트 각각을 문자 (E2 80 99)로 바보 변환하여 잘못된 문자열을 반환합니다. 이 시점에서 "loc"문자열은 쓸모가 없습니다. 유효한 유니 코드 문자열이 아닙니다. (각 문자가 웹 서버에서 전송 된 바이트의 값을 갖는 경우)

String loc = con.getHeaderField("Location"); 
    byte [] locbytes = new byte[loc.length()]; 
    for (int index = 0; index < locbytes.length; index++) 
    { 
    locbytes[index] = (byte) loc.charAt(index); 
    } 

    // use this loc instead 
    String loc2 = new String(locbytes, "UTF-8"); 

다시 바이트 배열에 가짜 문자열을 변환 : 여기

은 도움이 될 수 있습니다 해결 방법입니다. 그런 다음 적절한 문자 집합을 사용하여 바이트 배열을 다시 문자열로 변환합니다. 이제 loc2를 URL로 사용하여 새 연결을 엽니 다.

아마이 방법을 사용하는 것이 더 좋을지 모르지만 HttpURLConnection 클래스에 UTF-8로 인코딩 된 헤더 값을 처리하도록 알리는 방법이 있다는 것을 소스 구현에서 조사하지 않았습니다.

+0

당신의 솔루션은 완벽합니다. 고마워. – Pooya

관련 문제