【问题标题】:Saving JSON to file often breaks将 JSON 保存到文件经常中断
【发布时间】:2014-04-09 08:32:26
【问题描述】:

我试图找到答案,但也许我没有使用正确的术语来解决我的问题,所以我需要在这里提问:

我制作了一个 web 应用程序,它可以从 JSON 文件加载更大的对象数组。如果需要,用户将更新数组的某些部分、删除对象或推送新数据。

因为这个当用户决定使用 JQUERY AJAX 将数组保存回 JSON 文件时,在我处理数据的 PHP 中我使用 'w+' 标记 所以我删除了内容并写回全新的和修改过的内容。

问题在于即使 JSON 文件由单个用户使用,有时写入过程会在整个内容写入该清除的文件之前中断。这会导致重要的数据丢失。

// 我确实为备份文件节省了安全性,但这意味着每次保存中断时,我都必须将最后一个备份 JSON 文件复制到 webapp 加载数据的原始 JSON 文件,直到我这样做之前没有人可以使用我的网络应用程序。

这是我在 .js 文件中的 JQUERY AJAX:

$.ajax
({
    url: 'json/save_json.php',
    type: 'POST',
    dataType : 'json',
    data: { pid: currentdate, data: JSON.stringify(allinfobj), userlevel: jslevel},
    complete: function(){alert("this worked out!")};

});

我的 save_json.php:

<?php
$datecode = $_POST['pid'];
$myFile = "work".$datecode.".json";
$userData = $_POST['userlevel'];
if($userData != 4 && $userData != 3){
    $fh = fopen($myFile, 'w+') or die("Error while opening the file.");
    flock($fh, LOCK_EX);   // acquire an exclusive lock
    $stringData = $_POST['data'];
    fwrite($fh, $stringData);
    flock($fh, LOCK_UN);
    fclose($fh);
}
?>

我在那里使用某些变量,例如 $userData 或 $datecode。这些与 fwrite 中断的事实无关。希望它不会让任何人感到困惑,我向你保证这些工作良好。

生成的 JSON 文件通常类似于:

[{"name":"Apple","color":"red","quality";"awful"};{"name":"Tesla","color":"metallic","quality";"improved"};{"name":"Shoe","color":"white","quality";"fake"};{"name":"Glass","color":"undefined","quality";"good"};{"name":"Jessica","color":"private","quality";"private"}]

但有时我因为不明白的休息而导致的结果是这样的:

[{"name":"Apple","color":"red","quality";"awful"};{"name":"Tesla","color":"met

因此,下次用户无法加载此 JSON 数据,因为它缺少内容并且它永远不是正确的数组或 JSON。

a pr a+ 在 PHP 我认为这不是一个解决方案,因为我经常需要替换或删除数组中较旧的 JSON 对象,所以我无法通过附加到现有数据或新数组来逃避可能比旧的短。

仅供参考:在我的 ajax 调用中,success 和 error 标签不会做任何事情。我不知道为什么。 complete 有效,如您所见,我在代码中使用了它。

我希望我已经把自己说得很清楚了,我将非常感谢任何关于为什么写入 JSON 文件会中断的建议。我应该在哪里了解和解决这个问题。 谢谢!

【问题讨论】:

  • 向文件中写入任意代码非常容易。
  • 如果我发送一个像 some_file.php\0 这样的 pid(其中 \0 是空字符)然后像 data 那样输入一些 PHP 代码会发生什么。您可能认为攻击者不知道文件名中前置的work 字符串。但是可以通过执行相同的操作并读取异常结果在read_json.php 中猜到。
  • 你是绝对正确的。但是,我现在想重点关注数据泄露现象,然后当然是提高安全性,但毫无疑问地指出这种不安全性是件好事。

标签: javascript php jquery ajax json


【解决方案1】:

在将 Post 数据保存到文件之前,请检查它是否被截断。 如果您的 Json 数据正在增长,请检查 post_max_size。 保存文件时也尝试将 w+ 更改为 c 模式。 w+ 可以截断文件。

http://us3.php.net/manual/en/function.fopen.php

此链接也可以帮助您:

fopen(file,w+) truncates the file before I can check if it's locked with flock()

【讨论】:

  • 看起来将w+ 更改为c 并在使用ftruncate($fh,0) 和fflush($fh) 获得排他锁后解决了这个问题,因为经过超过24 小时的密集使用,部分截断问题确实发生了没出现。暂时我会将此标记为正确答案。我赞成所有答案,因为它们都或多或少地帮助我理解了这个问题。谢谢。
【解决方案2】:

既然你只写文件,那么你只需要w而不是w+。

但我认为这不会解决问题。

我认为您的服务器对POST 或GET 请求的大小有限制。

为了测试它,我建议您查看损坏的JSON 字符串的大小是否与您在PHP 配置中设置的限制相同。

请求的最大大小在max_input_vars of PHP.INI 中设置。

要测试您的 PHP 脚本中的数据是否正确,请尝试以下操作: 附加(在另一个文件中)您收到的 JSON 的大小。当它崩溃时,查看损坏的 JSON 字符串的大小是否与您在另一个文件中写入的长度相同。

另外,您可以通过 JS 发送JSON 字符串的客户端长度。然后,您可以将收到的长度与您在收到的字符串上计算的长度进行比较。

这将有助于区分问题是客户端还是服务器端。

【讨论】:

  • 谢谢,我会试一试,但是新的 JSON 文件在中断发生后会缩短,很难相信这就是原因。同样在用备份文件(大小大致相同)替换 JSON 文件后,即使它获得另外 10 或 20KB 的新数据,它也可以工作数天。
猜你喜欢
  • 1970-01-01
  • 2017-08-17
  • 1970-01-01
  • 1970-01-01
  • 2012-02-14
  • 2020-02-08
  • 2022-01-16
  • 2010-12-15
  • 2021-05-05
相关资源
最近更新 更多