0
votes

Main goal is send all data to remote mysql database. I'm using TidHTTP for POST method. Having nearly 10.000 records, around 2MB data. When I run delphi codes, upload json data. But some records doesn't insert.

Delphi Codes:

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;

Update 1: PHP Side After these update I'm getting "not parsed" response. About 2.5 MB is big data for JSON Parse?

Here codes:

<?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"]);

?>

Update 2: Delphi Side I changed ContentType as "application/json". And get json data throught RAW Data. But still json data doesn't decode.

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 Side: I think I'm right way. json_last_error() is giving me why doesn't decoded it.

<?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"]);
  } 
?>

**I found the reason. Simply tye reason is indy components version. ** I upgrade my codes to Delphi xe7 and now It's ok now.

1
Your code does not write error messages if the JSON can not be parsed - there is no else after in if($json!=null){ $decoded=json_decode($json,true); if(is_array($decoded["items"])) ...mjn
Ur PHP code also asks for someone taking full control of database out of your hands. bobby-tables.comArioch 'The
Now regarding your programs, I think you better to check who is in the wrong - Delphi code or PHP code - first and then make your question narrow and detailed. Also I think you'd better ZIP your packet before sending. Not that it only would reduce and fasten the traffic, it also would protect you from "only half of the packet received" scenario.Arioch 'The
Store the incoming JSON to a local file and use Notepad++ or a JSON validator / parser to find out where exactly is corrupted and causes the "not parsed".mjn
@RedLEON did you check the incoming JSON on the server side? Yes, the problem is the HTTP request, see my answer below.mjn

1 Answers

2
votes

Your HTTP client needs to use a different way to transfer the JSON data. Here is a basic example:

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.

Notes:

  • (1) you must not use a TStringList for the JSON body. That version of TIdHTTP.Post() formats the data according to the application/x-www-form-urlencoded media type, which is not appropriate for JSON and will corrupt it.

  • (2) make sure you encode the JSON body as UTF-8.