【问题标题】:How to ensure that no data get lost while transferring them to and storing them on the server?如何确保在将数据传输到服务器并存储在服务器上时不会丢失数据?
【发布时间】:2021-12-30 23:09:10
【问题描述】:

JavaScript:

const XHR = new XMLHttpRequest();

function sendData(data) {
  XHR.open('POST', 'savedata.php');
  XHR.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  XHR.send('data=' + JSON.stringify(data);
}

PHP:

if (isset($_POST['data'])) {
    if (file_exists('data.json')) {
        $file = file_get_contents('data.json');
        $accumulatedData = json_decode($file);
        $data = json_decode($_POST['data']);
        array_push($accumulatedData, $data);
        $encodedAccumulatedData = json_encode($accumulatedData);
        file_put_contents('data.json', $encodedAccumulatedData);
    }
}

如果数据传输之间的间隔很短,数据就会丢失。如何预防?

【问题讨论】:

  • 您担心上传的哪一部分?您是否因为暂时失去网络覆盖而担心传输错误?
  • 我并不担心,但我实际上已经注意到有一些数据对象没有存储在 JSON 数组中。数据传输之间的超时(例如 100 毫秒)不会发生这种情况。说实话,不知道是客户端还是服务器端造成的。

标签: javascript php json ajax


【解决方案1】:

这听起来像是一种竞争条件,可能是因为多个请求同时写入同一个 data.json 文件。

您应该能够通过锁定文件来防止这种情况发生,这样一次只有一个 PHP 进程可以访问它。

if (isset($_POST['data'])) {
    if (file_exists('data.json')) {
        $fp = fopen("data.json", "r+");
        // acquire an exclusive lock, block until we can aquire it.
        if (flock($fp, LOCK_EX)) {  
            // we can still use file_get_contents, which is better than using fread.
            $file = file_get_contents('data.json');
            $accumulatedData = json_decode($file);
            $data = json_decode($_POST['data']);
            array_push($accumulatedData, $data);
            $encodedAccumulatedData = json_encode($accumulatedData);
            // Remove existing file contents
            ftruncate($fp, 0); 
            // Write new JSON array to file
            fwrite($fp, $encodedAccumulatedData);
            // release the lock
            flock($fp, LOCK_UN);    
        } else {
            // This should rarely happen since flock will block until it can get a lock.
            // just in case, we should instruct the client to try again later.
            echo "Couldn't get the lock!";
        }
    }
}

【讨论】:

  • 请注意:“警告 在某些操作系统上,flock() 是在进程级别实现的。使用多线程服务器 API 时,您可能无法依赖在flock() 上保护文件免受在同一服务器实例的并行线程中运行的其他PHP脚本的影响!” (source)
猜你喜欢
  • 1970-01-01
  • 2020-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多