一、问题提出
    近期,由于与另一PHP程序之间,动态传递JSON数据,使用delphi XE10.4中idhttp控件实施。代码完成,出现三个问题:
    1、JSON文本定长自动加入“=”;
    2、英文和数字显示正常,中文显示为“????”;
    3、Post反馈的信息中,如有汉字不能显示。

    二、问题探索
    1、通过生成UTF8格式文件,再导入上传,显示的汉字不是“????”,而是乱码了。 

    StringStream := TStringStream.Create('', TEncoding.UTF8);
    StringStream.WriteString(Json1.ToString);
    StringStream.SaveToFile(FileName);

    2、通过实践,将Josnk 汉字转成UTF8格式,如:“中文汉字”,可以显示“中文汉字”。说明Post过程中,中文没有以UTF8格式传递。
    (1)首先在JSON字符生成时,改成UTF8,也不行。
    (2)HTTPEncode(Ansitoutf8(S)),Utf8Encode(s),HttpEncode(UTF8Encode(S)),UTF8Decode(HttpDecode(S2),偿试均失败。
    (3)AddFormField('data', '中文汉字', 'utf-8');  已指定utf-8格式,还是不行;
    3、换个思路,Delphi发展到XE10,在汉字轮换上不可以需要我们如此大费功夫,应该能很好地实现的,是否格式上有问题。同时,定长自动加入“=”问题,肯定在传递的格式(网络传输的字节流)有问题,经查TIdFormDataField有个ContentTransfer属性。

    IdMultipartFormData.pas单元文件中,ContentTransfer有三种类型:

const
  sContentTransferPlaceHolder = 'Content-Transfer-Encoding: %s';     
  sContentTransferQuotedPrintable = 'quoted-printable';              
  sContentTransferBinary = 'binary';                                 

    Delphi默认ContentTransfer第二种:sContentTransferQuotedPrintable,就是'引用可打印'; 它是7位可打印的 ASCII编码方式。每个高位为1的码翻译为如=A1的16进制模式。

    这种模式下,每76个字符用quoted-printable插入一次。这就是出现多余的=\\r\\n(“软”换行符)的原因。在支持quoted-printable服务器,都将在解码期间删除“软”换行符。

    由于对方服务器不支持quoted-printable,所以解码后,加入了“=”等字符。

    原因找到,那就换个模式吧。

    换Binary类型试试:   

  paramStream.AddFormField('data',jsonstr,'UTF-8').ContentTransfer := sContentTransferBinary;

    Post问题都解决。

    4、分析:
    (1)由于ContentTransfer默认sContentTransferQuotedPrintable,Post的'quoted-printable'格式,出现“=”字符。
    (2)设置ContentTransfer为sContentTransferBinary后,它是数据流传输格式,实现UTF-8完整传输。(这里值得斟酌:它不编码的10进制数据流)

    三、问题解决
 

procedure TMainFrm.Button5Click(Sender: TObject);
var paramStream: TIdMultiPartFormDataStream;
    vResponse: TStringStream;
    jsonstr: string;
    MyList:TStringList;
begin
  paramStream := TIdMultiPartFormDataStream.Create;
  vResponse := TStringStream.Create('');
  MyList:=TStringList.Create;
  jsonstr:=GetJosnTxt;                                  // 生成Json的自定义函数 
// 定义http消息头
  idhttp1.Request.ContentType := 'application/json';
//传递普通参数
  paramStream.AddFormField('data',jsonstr,'UTF-8').ContentTransfer := sContentTransferBinary;  // Binary格式传输       
// 执行Post
  IdHTTP1.Post('http://XXX.XXXX.com/api/v1/data', paramStream, vResponse); // 隐藏XXX 
  vres := vResponse.DataString;                         // Post返回值Utf8码
  Memo1.Text := UnicodeToChinese(vres);                 // 显示反馈信息Utf8To
  s:=FormatdateTime('yyyy-MM-dd HH:SS:mm',Now)+#13#10;
  sTemp:=sTemp+S+Memo1.Text;
  MyList:=TStringList.Create;
  MyList.Text:=sTemp;
  MyList.SaveToFile(sMainPath+'Upload.log');            // 保存Post信息 
  paramStream.Free;
  vResponse.Free;
end;

GitHub 加速计划 / js / json
41.72 K
6.61 K
下载
适用于现代 C++ 的 JSON。
最近提交(Master分支:1 个月前 )
960b763e 4 个月前
8c391e04 7 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐