Angular POST to PHP:file_put_contents没有写入/提交顺序错误

时间:2019-02-01 17:23:43

标签: php angular http post file-put-contents

我正在使用angular http将数据从Ionic应用程序发布到PHP脚本。在该脚本中,将读取并解码一个json文件,以便可以将传入的数据附加到文件中,然后再写回到该文件中。

这基本上可以正常工作,但是在某些情况下,file_put_contents不会写入新的编码数组和/或提交顺序变得混乱。

打字稿:

this.names.forEach(name => {
    this.http.post("http://myServer.test/saveNames.php", {name: name["name"], mode: name["mode"]}).subscribe(
        err => {
            errors.push(name["name"]);
        }
    );
});

打字稿信息:

(3) [{…}, {…}, {…}]
0: {name: "User 1", mode: "namesM"}
1: {name: "User 2", mode: "namesW"}
2: {name: "User 3", mode: "namesJobs"}
length: 3

PHP脚本:

$postData = file_get_contents("php://input");
    if (isset($postData)) {
    $request = json_decode($postData, true);

    var_dump("Data after decode:");
    var_dump($request);

    $inp = file_get_contents('names.json');

    if (($inp) == "") return; // Return so file does not get messed up

    $allNames = json_decode($inp, true);

    var_dump("File, no decode:");
    var_dump($inp);
    var_dump("File, decoded:");
    var_dump($allNames);

    $allNames[] = $request;

    var_dump("File content + new data:");
    var_dump($allNames);
    var_dump("All data pretty printed:");
    var_dump(json_encode($allNames, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));

    file_put_contents('names.json', json_encode($allNames, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); // mit UTF8s
}

names.json在写之前(初始状态):

[]
帖子完成后的

names.json:

[
    {
        "name": "User 1",
        "mode": "namesM"
    },
    null
]

该文件具有777权限,并且在此过程中未打开。如您所见,只写了一个名字,插入了一个空值,然后什么也没有发生。

当我检查铬网络选项卡,我注意到,用户1(其漂亮的印刷JSON看起来好)后,顺序弄乱。在用户1之后,紧接着是用户3,但是file_get_contents(names.json)返回了空数组,因此实际上未写入用户1。用户3也产生了正确的json,但是在此之后,用户2紧随其后,file_get_contents('names.json')为空(如在空字符串中),因此它在此处停止。

不过,我不知道如何在这一切之后,还是有用户1文件中,为什么其他两个人不是一般的写的。

这是我在Chrome网络标签中的var_dumps():

用户1(第一个):

string(18) "Data after decode:"
array(2) {
  ["name"]=>
  string(6) "User 1"
  ["mode"]=>
  string(6) "namesM"
}
string(16) "File, no decode:"
string(2) "[]"
string(14) "File, decoded:"
array(0) {
}
string(24) "File content + new data:"
array(1) {
  [0]=>
  array(2) {
    ["name"]=>
    string(6) "User 1"
    ["mode"]=>
    string(6) "namesM"
  }
}
string(24) "All data pretty printed:"
string(66) "[
    {
        "name": "User 1",
        "mode": "namesM"
    }
]"

用户3(秒!?):

string(18) "Data after decode:"
array(2) {
  ["name"]=>
  string(6) "User 3"
  ["mode"]=>
  string(9) "namesJobs"
}
string(16) "File, no decode:"
string(2) "[]"
string(14) "File, decoded:"
array(0) {
}
string(24) "File content + new data:"
array(1) {
  [0]=>
  array(2) {
    ["name"]=>
    string(6) "User 3"
    ["mode"]=>
    string(9) "namesJobs"
  }
}
string(24) "All data pretty printed:"
string(69) "[
    {
        "name": "User 3",
        "mode": "namesJobs"
    }
]"

用户2(第三!!)

string(18) "Data after decode:"
array(2) {
  ["name"]=>
  string(6) "User 2"
  ["mode"]=>
  string(6) "namesW"
}

对于冗长的文字,我感到非常抱歉,但是尝试了几个小时之后,我只是找不到解决方案。希望我对它进行了充分的记录,并感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

在我看来,这些问题均可能发生:

  1. 您正在运行PHP的Web服务器可能正在并行运行每个POST请求(多线程),这将导致文件部分打开或被一个请求忙于写入,而另一个正在忙于尝试写入。阅读。

  2. 您的网络服务器的文件系统告诉PHP该文件​​已写入,并且一切都很好,实际上,在将数据实际物理写入磁盘之前,它仍在忙于内部缓存数据。因此,当下一个读取文件的请求到来时,它尚未被完全写入。

因此,您可以尝试的解决方案是:

  1. 尝试使用带有LOCK_EX标志的file_put_contents和file_get_contents来专门读写文件。参见http://php.net/manual/en/function.file-put-contents.php

  2. 您为什么仍要从同一个客户端发送多个POST请求?您应该这样做:

var allNames = [];
this.names.forEach(name => {
    allNames.push({name: name["name"], mode: name["mode"]});
    });


this.http.post("http://myServer.test/saveNames.php", allNames, ....);

因此,一次发送全部名称数组,那么您将避免遇到此问题。

磁盘操作非常慢,因此您不应该依靠它们来满足来自客户端的请求。您应该只进行尽可能少的磁盘操作,并在尝试时尽可能多地对数据进行批处理。