2016-09-02 8 views
2

私のアプリケーションは "application/json"を使用してデータ(個人情報)を送信します。データが有効であれば、サーバーは "application/pdf"を通して私にPDFファイルを送り返します。しかし、RestResponseが到着すると、「ターゲットのマルチバイトコードページにUnicode文字のマッピングが存在しません」という例外が表示されます。私は何が起こっているのか分からない。私は過去4日間でこれについて取り組んでおり、私はこれを解決できません。例外は、行: "RRequest.Execute;"でポップアウトします。ここに私のコードの男です:RestResponseを使用してcontentType "application/pdf"を受信できません

procedure TThreadBoleto.Execute; 
var 
    RCtx : TRttiContext; 
    RType : TRttiType; 
    RProp : TRttiProperty; 
    I : integer; 
    PDF : TFile; 
begin 
    try 
    try 
     RClient := TRESTClient.Create(''); 
     with RClient do begin 
     AcceptEncoding := 'identity'; 
     FallbackCharsetEncoding := 'UTF-8'; 
     Accept := 'application/json;text/plain;application/pdf;'; 
     AcceptCharset := 'UTF-8'; 
     BaseURL := 'https://sandbox.boletocloud.com/api/v1/boletos'; 
     ContentType := 'application/x-www-form-urlencoded'; 
     HandleRedirects := true; 

     RCtx := TRttiContext.Create; 
     RType := RCtx.GetType(THRBoleto.ClassType); 
     I := 0; 
     for RProp in RType.GetProperties do 
     begin 
      Params.AddItem; 
      Params.Items[I].name := LowerCase(RProp.Name.Replace('_','.')); 
      Params.Items[I].Value := RProp.GetValue(THRBoleto).AsString; 
      I := I + 1; 
     end; 
     end; 

     RRequest := TRESTRequest.Create(RRequest); 
     with RRequest do begin 
     Accept := 'application/json;text/plain;application/pdf;'; 
     Client := RClient; 
     Method := rmPost; 
     SynchronizedEvents := false; 
     AcceptCharset := 'UTF-8'; 
     end; 

     RResponse := TRESTResponse.Create(RResponse); 
     RResponse.ContentType := 'application/pdf;*/*;'; 
     RResponse.ContentEncoding := 'UTF-8'; 

     RAuth := THTTPBasicAuthenticator.Create('',''); 
     with RAuth do begin 
     Username := 'anAPItokenAccess'; 
     Password := 'token'; 
     end; 

     RClient.Authenticator := RAuth; 
     RRequest.Response := RResponse; 

     RRequest.Execute; 
     PDF.WriteAllBytes(ExtractFilePath(Application.ExeName)+'boleto.pdf',RResponse.RawBytes); 
     OutputStrings.Add(RResponse.Content); 
     OutputStrings.Add(''); 
     OutputStrings.Add(''); 
     OutputStrings.AddStrings(RResponse.Headers); 
    except on E:Exception do 
     ShowMessage('Error: '+E.Message); 
    end; 
    finally 
    THRBoleto.Free; 
    end; 
end; 

答えて

5

あなたはエラーがRRequest.Execute()呼び出しで起こっているのか? RResponse.Contentプロパティを読み取ったときにPDFデータをStringとして受信しようとしているため、代わりにその呼び出しでUnicodeエラーが発生することが予想されます。 PDFファイルはテキストデータではなく、バイナリデータなので、受信する安全な方法はRResponse.RawBytesプロパティのみです。

また、RResponse.ContentTypeまたはというプロパティを設定しないでください(とにかく無効な値に設定することは言うまでもありません)。彼らは受け取った実際の応答に従って記入されます。

あなたが反応して受け入れようとしている3種類のメディアタイプを含めるようにRRequest.Acceptプロパティを設定しているので、あなたが実際にRawBytesを保存する前にPDFファイルを受信して​​いることを確認するRResponse.ContentTypeプロパティの値を調べる必要がありますファイル.pdfに転送します。代わりにテキストまたはJSON応答を受け取った場合は、PDFとして処理することはできません。

個人的には、私はRESTコンポーネントがかなりバグであることがわかります。あなたはインディのTIdHTTP代わりに、例えば使用して、より良い運を持っているかもしれません:

uses 
    ..., IdGlobal, IdGlobalProtocols, IdHTTP, IdSSLOpenSSL; 

procedure TThreadBoleto.Execute; 
var 
    RCtx : TRttiContext; 
    RType : TRttiType; 
    RProp : TRttiProperty; 
    Client: TIdHTTP; 
    Params: TStringList; 
    Response: TMemoryStream; 
begin 
    Client := TIdHTTP.Create; 
    try 
    with Client.Request do begin 
     AcceptEncoding := 'identity'; 
     Accept := 'application/json;text/plain;application/pdf'; 
     AcceptCharset := 'UTF-8'; 
     ContentType := 'application/x-www-form-urlencoded'; 
     BasicAuthentication := True; 
     Username := 'anAPItokenAccess'; 
     Password := 'token'; 
    end; 
    Client.HandleRedirects := true; 

    RCtx := TRttiContext.Create; 
    RType := RCtx.GetType(THRBoleto.ClassType); 

    Response := TMemoryStream.Create; 
    try 
     Params := TStringList.Create; 
     try 
     for RProp in RType.GetProperties do 
      Params.Add(LowerCase(RProp.Name.Replace('_','.')) + '=' + RProp.GetValue(THRBoleto).AsString); 

     Client.Post('https://sandbox.boletocloud.com/api/v1/boletos', Params, Response); 
     finally 
     Params.Free; 
     end; 

     Response.Position := 0; 
     case PosInStrArray(ExtractHeaderMediaType(Client.Response.ContentType), ['application/pdf', 'application/json', 'text/plain'], False) of 
     0: begin 
      // save PDF 
      Response.SaveToFile(ExtractFilePath(Application.ExeName)+'boleto.pdf'); 
      OutputStrings.Add('[PDF file]'); 
     end; 
     1: begin 
      // process JSON as needed 
      OutputStrings.Add(ReadStringAsCharset(Response, Client.Response.Charset)); 
     end; 
     2: begin 
      // process Text as needed 
      OutputStrings.Add(ReadStringAsCharset(Response, Client.Response.Charset)); 
     end; 
     else 
     // something else! 
     OutputStrings.Add('[Unexpected!]'); 
     end; 
    finally 
     Response.Free; 
    end; 

    OutputStrings.Add(''); 
    OutputStrings.Add(''); 
    OutputStrings.AddStrings(Client.Response.RawHeaders); 
    finally 
    Client.Free; 
    end; 
end; 

procedure TThreadBoleto.DoTerminate; 
begin 
    if FatalException <> nil then 
    begin 
    // Note: ShowMessage() is NOT thread-safe! 
    ShowMessage('Error: ' + Exception(FatalException).Message); 
    end; 
    THRBoleto.Free; 
    inherited; 
end; 
+0

私がテストしていますが...しかし、それは私にエラーを与える:「SSLライブラリをロードできませんでした」。 DLLファイルはSystemおよびSysWow64に存在し、EXEのフォルダにも存在します。 – RafaelHarth

+0

最新のDLLはありますか? OpenSSLのどのバージョン?障害が発生した後、Indyの 'IdSSLOpenSSLHeaders.WhichFailedToLoad()'関数は何を言っていますか? –

+0

DLLファイルが動作しています。私はちょうど更新よりも。 – RafaelHarth

関連する問題