我在 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;
所以现在,出现了新的问题:
为什么相同的程序在 Windows 7 下的 Delphi 10.3.1 Tokyo 中运行良好,但现在在 Windows 10 上的 Delphi 10.4 Sydney(补丁 1、2、3)中它需要 UTF-8 编码?是 Delphi 10.4 的问题吗?是 Windows 10 的问题吗?
在我的原始服务器端代码中,我有许多端点使用命令发送响应
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;
...