Угловой POST в PHP: file_put_contents не пишет / неверный порядок отправки - PullRequest
0 голосов
/ 01 февраля 2019

Я использую угловой 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 разрешений и не был открыт во время процесса.Как видите, было написано только одно имя, было вставлено одно значение NULL, а затем ничего не произошло.

Когда я проверил вкладку сети Chrome, я заметил, что после Пользователя 1 (чей довольно напечатанный json выглядел хорошо) порядок был испорчен.После пользователя 1 пользователь 3 был следующим, однако file_get_contents(names.json) вернул пустой массив, поэтому пользователь 1 фактически не был записан.Пользователь 3 также дал правильный json, но после этого появился пользователь 2, и file_get_contents('names.json') был пуст (как в пустой строке), поэтому он остановился здесь.

Однако я не понимаю, как все-такичто в файле все еще есть Пользователь 1 и почему два других не написаны вообще.

Вот мои var_dumps () на вкладке сети Chrome:

Пользователь 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 голосов
/ 03 февраля 2019

Мне кажется, что может возникнуть любая из этих проблем:

  1. Веб-сервер, на котором вы запускаете PHP, может запускать каждый запрос POST параллельно (многопоточность), чтоприведет к тому, что файл будет частично открыт или занят записью одним запросом, в то время как другой пытается его прочитать.

  2. Файловая система вашего веб-сервера сообщает PHP, что файл записан ивсе хорошо, хотя на самом деле он все еще занят кэшированием данных внутри, прежде чем они физически записываются на диск.Поэтому, когда приходит следующий запрос на чтение файла, он еще не полностью записан.

Итак, вы можете попробовать следующие варианты:

  1. Попробуйте использовать file_put_contents и file_get_contents с флагом LOCK_EX для исключительно чтения и записи файла.См. 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, ....);

Так что отправляйте весь массив имен одновременно, тогда вы не столкнетесь с этой проблемой.

Дисковые операции очень медленные, поэтому вам не следует рассчитывать на то, что они будут соответствовать запросам ваших клиентов.Вам следует выполнять как можно меньше операций с диском и стараться как можно чаще собирать данные, когда вы это делаете.

...