2013-11-20 2 views
4

Delphi XE5의 새로운 TRest 구성 요소를 사용하여 트윗을 보내고 싶습니다. IS0-8859-1 문자가 포함 된 트윗을 UTF8로 인코딩 할 수있는 방법을 찾고 있습니다. 아래의 코드는 작동하지만 코드 페이지 변환 등이 포함됩니다. 더 좋은 방법입니까? 누군가?TRestClient에서 UTF-8로 인코딩 된 문자열 지원 Delphi XE5

procedure TTwitterApi.Send(Tweet: string); 
begin 
    Reset; 

    // Encode as UTF8 within (UTF-16 Delphi) string 
    Tweet := EncodeAsUTF8(Tweet); 

    FRestRequest.Resource := '1.1/statuses/update.json'; 
    FRestRequest.Method := rmPOST; 
    FRestRequest.Params.AddItem('status', Tweet, pkGETorPOST); 
    FRestRequest.Execute; 
end; 


function TTwitterApi.EncodeAsUTF8(UnicodeStr: string): string; 
var 
    UTF8Str: AnsiString; 
    TempStr: RawByteString; 
begin 
    TempStr := UTF8Encode(UnicodeStr); 
    SetLength(UTF8Str, Length(TempStr)); 
    Move(TempStr[1], UTF8Str[1], Length(UTF8Str)); 
    Result := UTF8Str; 
end; 

답변

5

트위터의 1.1/statuses/update.json URL 데이터가 application/x-www-form-urlencoded 형식으로 인코딩 할, 그래서 당신은 (기본값 ctNone로 설정) ctAPPLICATION_X_WWW_FORM_URLENCODEDTRESTClient.ContentType 속성을 설정해야합니다 기대하고있다. UTF-8로

TRESTClient 내부적 인디를 사용하고, 인디, 사용자가 지정한 캐릭터 세트를 사용하여 아웃 바운드 데이터를 인코딩 지원하지만 엠바 카데 그 TRESTClient 인터페이스에 해당 기능을 추가하는 것이 나타나지 않는다 (이는 비록 반응의 캐릭터 세트를 처리하지). 왜 Embarcadero가 그러한 중요한 기능을 생략할지 모르겠습니다. 문자열 데이터를 UTF-8로 인코딩하는 것만으로는 충분하지 않지만, Twitter에 데이터가 UTF-8로 인코딩되었다고 ( charset Content-Type REST의 속성을 통해) 알려줘야합니다. 헤더), TRESTClient은 내가 볼 수있는 한 그렇게 할 수 없습니다. TRESTClient이 기본 charset을 지정하여 REST 요청을 보내는 지 알지 못하지만 소스를보고 있으면 생각하지 않습니다.하지만 시도하지는 않았습니다.

적어도 최소한 EncodeAsUTF8() 기능을 수정해야합니다. 생각하는 것처럼 UTF-8로 인코딩 된 8 진수를 보유하는 UnicodeString을 생성하지 않습니다. AnsiString으로 인코딩 된 UTF-8을 생성 한 다음 RTL의 기본 Ansi 코드 페이지를 사용하여 UTF-16으로 인코딩 된 UniodeString으로 변환하여 UTF-8 데이터가 손실되는 데이터 변환을 호출합니다. 대신이 시도 :

function TTwitterApi.EncodeAsUTF8(UnicodeStr: string): string; 
var 
    UTF8Str: UTF8String; 
    I: Integer; 
begin 
    UTF8Str := UTF8String(UnicodeStr); 
    SetLength(Result, Length(UTF8Str)); 
    for I := 1 to Length(UTF8Str) do 
    Result[I] := Char(Ord(UTF8Str[I])); 
end; 

TRESTClient은을 URL 인코딩을 할 수 있도록해야한다 자사의 POST 데이터의 올바른 UTF-8 데이터를, 적어도. 하지만 charset이 지정되지 않은 경우 트위터의 기본값이 UTF-8이 아닌 경우 Content-Type 요청 헤더에 누락 된 charset 속성 문제를 처리해야합니다. 당신이 TRESTClient 문제를 중심으로 작업하는 나는이 TRESTClient보다 더 정확한 application/x-www-form-urlencoded 구현하는을 사용하고있다 (대신 인디의 TIdHTTP 구성 요소로 전환 제안, 당신을 위해 작동하지 않는 것을 발견하면이 모든 것을 가진 자

는 말했다), 예를 들면 :

procedure TTwitterApi.Send(Tweet: string); 
var 
    Params: TStringList; 
begin 
    Reset; 

    Params := TStringList.Create; 
    try 
    FParams.Add('status=' + Tweet); 
    FIdHTTP.Request.ContentType := 'application/x-www-form-urlencoded'; 
    FIdHTTP.Request.Charset := 'utf-8'; 
    FIdHTTP.Post('https://api.twitter.com/1.1/statuses/update.json', Params, IndyTextEncoding_UTF8); 
    finally 
    Params.Free; 
    end; 
end; 
+0

각 문자 인코딩. 감사! – user3012503

+0

REST.Client 모듈에서 ContentType을 살펴 보았습니다. POST에서는 ContentType이 요청 매개 변수에서 가져옵니다. (Se 라인 2569 : LContentType : = ContentType;) contenttype이 ctNone이면 실제로 APPLICATION_X_WWW_FORM_URLENCODED로 끝납니다. 그래서 ContentType apper가 정확합니다. – user3012503

+0

UTF-8을 charset으로 설정하는 방법은 없지만 Twitter에서는 UTF-8 만 허용하므로이 방법이 효과적입니다. – user3012503

0

TRestRequest 내가 해결할 수 없다는 것을, 그것은 특별히 UTF8로, 많은 문제가 발생, 안드로이드와 함께 작동하지 않는, IdHttp 인디는 어떻게 잘 작동합니다.

0

나는 다음과 같은 방법으로 다른 API 제공 업체 (하지 트위터)와 함께이 문제를 해결했습니다 UTF8 지금 작품으로

function EncodeAsUTF8(UnicodeStr: string): AnsiString; // <-- Note the Ansi 
var 
    UTF8Str: UTF8String; 
    I: Integer; 
begin 
    UTF8Str := UTF8String(UnicodeStr); 
    SetLength(Result, Length(UTF8Str)); 
    for I := 1 to Length(UTF8Str) do 
    Result[I] := AnsiChar(Ord(UTF8Str[I])); // <-- Note the Ansi 
end; 

... 

fRESTClient1 := TRESTClient.Create(nil); 
fRESTClient1.Accept := 'application/json'; 
fRESTClient1.AcceptCharset := 'UTF-8'; 
fRESTClient1.AcceptEncoding := 'identity'; 
fRESTClient1.ContentType := 'application/x-www-form-urlencoded'; 

... 

rrOrder := TRESTRequest.Create(nil); 
rrOrder.Accept := 'application/json'; 
rrOrder.AcceptCharset := 'UTF-8'; 
rrOrder.Client := fRESTClient1; {} 
rrOrder.Method := rmPOST; 
rrOrder.Resource := 'xxxxxx'; 
rrOrder.Params.AddItem('', EncodeAsUTF8(aJson), pkREQUESTBODY, [poDoNotEncode]); 

rrOrder.Execute;