无法接收contentType" application / pdf"使用RestResponse

时间:2016-09-02 13:55:50

标签: rest delphi pdf client

我的应用程序使用" application / json"发送数据(个人信息)。如果数据有效,则服务器通过" application / pdf"向我发回PDF文件。但是当RestResponse到达时,会弹出一个异常:"目标多字节代码页"中不存在unicode字符的映射。我不知道发生了什么事。我在过去的4天里正在研究这个问题,我无法解决这个问题。在行中弹出异常:" RRequest.Execute;"。这是我的代码人员:

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;

1 个答案:

答案 0 :(得分:5)

您确定RRequest.Execute()来电时发生了错误吗?当您阅读String属性时,您试图以RResponse.Content的形式接收PDF数据,因此我希望在该调用上出现Unicode错误。 PDF文件不是文本数据,而是二进制数据,因此接收它的唯一安全方法是使用RResponse.RawBytes属性。

此外,您根本不应设置RResponse.ContentTypeRResponse.ContentEncoding属性(更不用说您将它们设置为无效值)。它们将根据收到的实际响应填写。

由于您要将RRequest.Accept属性设置为包含您愿意在响应中接受的3种不同媒体类型,因此您需要查看RResponse.ContentType属性值以确保实际接收将RawBytes保存到.pdf文件之前的PDF文件。如果您收到文本或JSON响应,则无法将其作为PDF处理。

就个人而言,我发现REST组件非常缺陷。你可能会更好地使用Indy的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;