0

我在 Windows 10 64bit 上使用 Delphi 10.4(带有补丁 1、2 和 3)来构建 VCL Web 客户端应用程序。

我有一个在 RAD 服务器上运行的 API,我可以使用下面的 VCL Webclient 应用程序毫无问题地从中获取信息。但是,当我尝试通过方法将数据插入 API 资源时,我从方法调用POST中收到以下错误消息:TRESRequest.Execute()

目标多字节代码页中不存在 Unicode 字符的映射

虽然我收到此错误消息,但 JSON 数据正在发送到 API 并正确保存到数据库中。似乎在该Execute()方法的某个时刻,在将数据发送到服务器后会产生错误。

我已经尝试过TEncoding.UTF8.GetBytes(),TEncoding.ASCII.GetBytes()Unicode, 没有成功。

这是我的代码:

procedure TForm1.BTPostClick(Sender: TObject);
var
  strjson : string;
  jo      : TJSONObject;
begin
  strjson :=
    '{'                                 +
      '"CUST_ID": 1500,'                +
      '"CUST_NAME": "John Doe Max",'    +
      '"CUST_COUNTERTOTAL": "500",'     +
      '"CUST_DETAILS": "This is just a test"' +
    '}';    

  //    jo := TJSONObject.ParseJSONValue(TEncoding.Unicode.GetBytes(StrJson),0) as TJSONObject;
  //    jo := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(StrJson),0) as TJSONObject;
  jo := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(StrJson),0) as TJSONObject;    

  Memo1.Clear;
  Memo1.Lines.Add(jo.ToString);

  RestRequest1.ClearBody;
  RestRequest1.Method := rmPost;
  RestResponse1.ResetToDefaults;
  RestRequest1.AddBody(jo);
  RestRequest1.Execute;   // ==> error: No mapping for the Unicode character exists in the target multi-byte code page
end;

服务器端代码:

procedure TMytestResource1.MytestPost(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
  s : string;
  i : integer;
  jo : TJSONObject;
begin
  jo := TJSONObject.Create;
  jo.AddPair('Response Line 1','Apple is maçã');
  jo.AddPair('Response Line 2','Foot is pé ');
  jo.AddPair('Response Line 3','There is lá');
  jo.AddPair('Exceção  Line 3',TJsonString.Create('Exception is exceção'));
  //s := jo.ToString;  at this point the characters has accents
  AResponse.Body.SetValue(jo, True);
end;

REST 组件的配置如下:

RestClient1.Accept          := 'application/json, text/plain; q=0.9, text/html;q=0.8,';
RestClient1.AcceptCharset   := 'utf-8;q=0.8';
RestClient1.AcceptEnconding := 'utf-8';
RestClient1.FallbackCharsetEncoding := 'utf-8';
RestClient1.ContentType    := 'application/json'
    
RestRequest1.Accept          := 'application/json, text/plain; q=0.9, text/html;q=0.8,'
RestRequest1.AcceptCharset   := 'utf-8;q=0.8';
    
RestResponse1.ContentEncoding := '';
RestResponse1.ContentType := '';

新的服务器端代码(工作正常)

procedure TMytestResource1.CadastraUser(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
  s : string;
  i : integer;
  jo : TJSONObject;
  Strm : TStringStream;
begin
  jo := TJSONObject.Create;
  jo.AddPair('Response Line 1','Apple  is maçã');
  jo.AddPair('Response Line 2','Foot   is pé');
  jo.AddPair('Response Line 3','There  is lá');
  jo.AddPair('Response Line 4','Useful is útil');

  //AResponse.Headers.SetValue('Content-Type', 'application/json; charset=utf-8');  ==> This line does not make any effect on response

  try
    // Strm := TStringStream(jo.ToJSON, TEncoding.UTF8); ==> does not work.
    Strm := TStringStream.Create(jo.ToJSON, TEncoding.UTF8);
    // AResponse.Body.SetStream(Strm, 'application/json; charset=utf-8', true); ==> This line causes an error on VCL WebClient during RestRequest.Execute() method , error is "Invalid enconding name."

    AResponse.Body.SetStream(Strm, 'application/json', true); // this works fine.
  finally
    jo.Free;
  end;   
end;

所以现在,出现了新的问题:

  1. 为什么相同的程序在 Windows 7 下的 Delphi 10.3.1 Tokyo 中运行良好,但现在在 Windows 10 上的 Delphi 10.4 Sydney(补丁 1、2、3)中它需要 UTF-8 编码?是 Delphi 10.4 的问题吗?是 Windows 10 的问题吗?

  2. 在我的原始服务器端代码中,我有许多端点使用命令发送响应 AResponse.Body.SetValue(myJSONObject, True);我应该用两个新命令替换所有端点吗?

    Strm := TStringStream.Create(jo.ToJSON, TEncoding.UTF8);
    AResponse.Body.SetStream(Strm, 'application/json', true);
    

发生错误的 REST.Client 单元的代码:

Procedure TCustomRestRequest.Execute 

...
              if LMimeKind <> TMimeTypes.TKind.Binary then
              begin
                LEncoding := TEncoding.GetEncoding(FClient.FallbackCharsetEncoding);  //==> This line is returning nil, though FClient.FallbackCharsetEncoding is filled with 'utf-8'
                LContentIsString := True;
              end;
            end
            else
            begin
              // Even if no fallback, handle some obvious string types
              if LMimeKind = TMimeTypes.TKind.Text then
                LContentIsString := True;
            end;
          end;
          if LContentIsString then
            LContent := FClient.HTTPClient.Response.ContentAsString(LEncoding); // ==> this line is generating the error 
        finally
          LEncoding.Free;
        end;
...
4

0 回答 0