【问题标题】:Delphi 7 idHTTP JSON Data Null ResultDelphi 7 idHTTP JSON数据空结果
【发布时间】:2015-11-22 05:01:41
【问题描述】:

主要目标是将所有数据发送到远程mysql数据库。 我将 TidHTTP 用于 POST 方法。拥有近 10.000 条记录,大约 2MB 数据。当我运行delphi代码时,上传json数据。但是有些记录没有插入。

德尔福代码:

function TFrmUploadDataWithJSON.PostJS(JS: string): string;
var
  lStream: TStringStream;
  parameters: TStringList;

begin
  IdHTTP1.Request.ContentType := 'application/x-www-form-urlencoded';
  lStream := TStringStream.Create(Result);
  try
    Parameters := TStringList.Create;
    parameters.Add('js=' + JS);
    IdHTTP1.Post('http://domain.com/uploadi.php', parameters,lStream);
    lStream.Position := 0;
    Result := lStream.ReadString(lStream.Size);
  finally
    //FreeAndNil(lHTTP);
    FreeAndNil(lStream);
  end;
end;

更新 1:PHP 端 在这些更新之后,我得到“未解析”的响应。大约 2.5 MB 是 JSON Parse 的大数据?

这里代码:

<?php
  include_once dirname(__FILE__) .'/DBConnect.php';

  function update($json){    
    $db = new DbConnect();

    $response = array();
    $res=array();

    if($json!=null){
      $done = 0;
      $fail = 0;

      $mErr = "";

      $decoded=json_decode($json,true);

      //$decode= var_dump($decoded);
      //$ss=$decode["array"];
      //echo $decoded['number'];
      if(is_array($decoded["items"]))
      {
        foreach($decoded["items"] as $items)
        {
          $a=$items["a"];
          $b=$items["b"];

          mysql_query("delete from `items` where `code` = '$a'") or $mErr = $mErr ."-". mysql_error();        
          //header("Content-Type: application/json; charset=utf-8", true);

          $sqlstr = "INSERT INTO items (`code`, `numune_id`) VALUES ('$a', '$b')";

          $result = mysql_query($sqlstr) or  $mErr = $mErr ."-". mysql_error();
          if ($result) {
            $done = $done + 1;
          } else {
            $fail = $fail + 1;
          }
        }

        $response["done"] = $done;
        $response["fail"] = $fail;
        $response["mysql errors"] =  $mErr;
        if ($fail > 0) 
          $response["error"] = "must be repost";

      } else {
        $response["error"] = "json not parsed";
      }
    } else {      
      $response["error"] = "json not posted";

    }

    // echoing JSON response
    echo json_encode($response);
  }


    update($_POST["js"]);

?>

更新 2:Delphi 端 我将 ContentType 更改为“application/json”。并通过 RAW Data 获取 json 数据。但是json数据仍然没有解码。

function PostJS(AFormat, JS: string): string;
var
  IdHTTP: TIdHTTP;
  RBody: TStringStream;
  params: TStringList;

begin
  IdHTTP := TIdHTTP.Create(self);
  RBody := TStringStream.Create(Result);

  IdHTTP.OnWork := IdHTTP1Work;
  IdHTTP.OnWorkBegin := IdHTTP1WorkBegin;
  IdHTTP.OnWorkEnd := IdHTTP1WorkEnd;

  try
    Params := TStringList.Create;
    params.Add('js=' + JS);
    params.Add('command=a1b234lTrLKMDEk');

    if AFormat = 'json' then
    begin
      IdHTTP.Request.Accept := 'text/javascript';
      IdHTTP.Request.ContentType := 'application/json';
      IdHTTP.Request.ContentEncoding := 'utf-8';
    end
    else
    begin
      IdHTTP.Request.Accept := 'text/xml';
      IdHTTP.Request.ContentType := 'text/xml';
      IdHTTP.Request.ContentEncoding := 'utf-8';
    end;

    IdHTTP.Post('http://domain.com/upload.php',params, RBody);

    RBody.Position := 0;
    Result := RBody.ReadString(RBody.Size);
  finally
    FreeAndNil(RBody);
    FreeAndNil(IdHTTP);
  end;
end;

PHP 端: 我想我是对的。 json_last_error() 告诉我为什么不解码它。

<?php
  include_once dirname(__FILE__) .'/DBConnect.php';

  function update($json){    

    $db = new DbConnect();

    $response = array();
    $res=array();

    if($json!=null){
      $done = 0;
      $fail = 0; 

      $mErr = "";

      $decoded=json_decode($json,true);

      if(is_array($decoded["items"]))
      {
        foreach($decoded["items"] as $items)
        {
          $a=$items["a"];
          $b=$items["b"];


          mysql_query("delete from `items` where `code` = '$a'") or $mErr = $mErr ."-". mysql_error();        

          $sqlstr = "INSERT INTO items (`code`, `numune_id`) VALUES ('$a', '$b')";

          $result = mysql_query($sqlstr) or  $mErr = $mErr ."-". mysql_error();
          if ($result) {
            $done = $done + 1;
          } else {
            $fail = $fail + 1;
          }
        }

        $response["done"] = $done;
        $response["fail"] = $fail;
        $response["mysql err"] =  $mErr;
        if ($fail > 0) 
          $response["error"] = "must be repost";

      } else {

        $response["error"] = "json not parsed";
        switch (json_last_error()) {
            case JSON_ERROR_NONE:
                $e1= ' - No errors';
            break;
            case JSON_ERROR_DEPTH:
                $e1= ' - Maximum stack depth exceeded';
            break;
            case JSON_ERROR_STATE_MISMATCH:
                $e1= ' - Underflow or the modes mismatch';
            break;
            case JSON_ERROR_CTRL_CHAR:
                $e1= ' - Unexpected control character found';
            break;
            case JSON_ERROR_SYNTAX:
                $e1= ' - Syntax error, malformed JSON';
            break;
            case JSON_ERROR_UTF8:
                $e1= ' - Malformed UTF-8 characters, possibly incorrectly encoded';
            break;
            default:
                $e1= ' - Unknown error';
            break;
        }
        $response["message"] =$e1;
        $response["json"] = $json;
      }
    } else {       
      $response["error"] = "json not posted";

    }

    // echoing JSON response
    echo json_encode($response);
  }

  parse_str(file_get_contents("php://input"),$post_vars);

  if ($post_vars["command"] == 'a1b234lTrLKMDEk') {
    update($post_vars["js"]);
  } 
?>

**我找到了原因。简单的原因是 indy 组件版本。 ** 我将代码升级到 Delphi xe7,现在可以了。

【问题讨论】:

  • 如果无法解析 JSON,您的代码不会写入错误消息 - if($json!=null){ $decoded=json_decode($json,true); if(is_array($decoded["items"])) ...
  • 你的 PHP 代码还要求有人从你手中完全控制数据库。 bobby-tables.com
  • 现在关于你的程序,我认为你最好先检查谁错了——Delphi 代码或 PHP 代码——然后让你的问题变得更窄更详细。另外我认为你最好在发送前压缩你的数据包。不仅可以减少和加快流量,还可以保护您免受“仅收到一半数据包”的情况。
  • 将传入的 JSON 存储到本地文件,并使用 Notepad++ 或 JSON 验证器/解析器找出损坏的确切位置并导致“未解析”。
  • @RedLEON 你检查了服务器端的 incoming JSON 吗?是的,问题出在 HTTP 请求上,请看下面我的回答。

标签: php mysql json delphi indy


【解决方案1】:

您的 HTTP 客户端需要使用不同的方式来传输 JSON 数据。这是一个基本示例:

uses
  IdHTTP, IdGlobal, SysUtils, Classes;

var
  HTTP: TIdHTTP;
  RequestBody: TStream;
  ResponseBody: string;
begin
  HTTP := TIdHTTP.Create;
  try
    try
      RequestBody := TStringStream.Create('{... (JSON) ...}', // (1)
        TEncoding.UTF8); // (2)
      try
        HTTP.Request.Accept := 'application/json';
        HTTP.Request.ContentType := 'application/json';
        ResponseBody := HTTP.Post('http://example.com/post', RequestBody);
      finally
        RequestBody.Free;
      end;
      WriteLn(ResponseBody);
      WriteLn(HTTP.ResponseText);
    except
      on E: EIdHTTPProtocolException do
      begin
        WriteLn(E.Message);
        WriteLn(E.ErrorMessage);
      end;
      on E: Exception do
      begin
        WriteLn(E.Message);
      end;
    end;
  finally
    HTTP.Free;
  end;
end.

注意事项:

  • (1) 不得将 TStringList 用于 JSON 正文。该版本的TIdHTTP.Post() 根据application/x-www-form-urlencoded 媒体类型格式化数据,这不适合JSON,会损坏它。

  • (2) 确保将 JSON 正文编码为 UTF-8。

【讨论】:

  • 我在一些网页上找到了类似的解决方案。您可能对内容类型“application/json”是正确的。但这一次又出现了一个问题:如何用php解析和响应?我正在使用“application/x-www-form-urlencoded”,添加“js”参数。并像 html 表单一样发布它们。在 PHP 方面,我使用 $_Post["js"] 命令获取 JSON 数据。
  • @RedLEON 对不起,我不知道 PHP 是怎么做的
  • 谢谢 mjn。我会找到怎么做的。
  • application/x-www-form-urlencoded 是发布 JSON 数据(或任何非网络表单数据)时使用的错误格式。 TStrings 版本的TIdHTTP.Post() 使用该格式。将 JSON 发布为 TStream 是正确的方法。服务器将按原样接收原始 JSON 数据。 PHP 可以使用php://input$HTTP_RAW_POST_DATA 访问该原始数据。 $_POST 仅适用于 application/x-www-form-urlencodedmultipart/form-data 帖子。
  • 谢谢@RemyLebeau。我使用了php://input,它工作正常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-26
  • 1970-01-01
  • 1970-01-01
  • 2016-04-06
  • 1970-01-01
  • 1970-01-01
  • 2014-12-26
相关资源
最近更新 更多