【问题标题】:JSON file generated by PHP has application/octet-stream mime typePHP 生成的 JSON 文件具有 application/octet-stream mime 类型
【发布时间】:2017-05-21 01:26:39
【问题描述】:

我有一个从数据生成 JSON 文件的脚本。 我有第二个脚本,它从目录中读取文件以仅获取 JSON 文件并将它们插入 DB。

问题是第二个脚本从我生成的文件中检测到“application/octet-stream”MIME 类型而不是application/json

我不想允许application/octet-stream MIME 类型,因为它可以是任何东西(出于安全原因:第二个脚本加载目录中的所有json 文件(不仅是生成的文件))。

那么无论如何要“设置”文件的 MIME 类型吗?

生成文件的代码:

if($r_handle = fopen($s_file_name, 'w+')){
    fwrite($r_handle, json_encode($o_datas, JSON_HEX_QUOT | JSON_HEX_TAG));
    fclose($r_handle);
    return;
}

读取 JSON 文件的代码:

$o_finfo = finfo_open(FILEINFO_MIME_TYPE);
$a_mimes =& get_mimes();
if(is_dir($s_dir) && $r_handle = opendir($s_dir)){
    while($s_file = readdir($r_handle)){
        $s_file_path = $s_dir.$s_file;
        $s_mime      = finfo_file($o_finfo, $s_file_path);
        if(!in_array($s_file, array('.', '..')) && in_array($s_mime, $a_mimes['json'])){
            // Some code
        }
    }
}

【问题讨论】:

  • 不,您不能“设置” MIME 类型。 Finfo 只是尽其所能猜测。 “application/octet-stream”几乎意味着“不知道,我猜这是一个文件”。哪个是技术上的正确答案……
  • 如果我理解这个问题,你可以在 PHP 中设置 header()fopen() 文件中的内容类型,对吧?
  • @SteveKnau : 我可以先header() 然后fopen() 然后fwrite() 然后fclose() 吗?
  • 那不会有任何用处,不。
  • 专门针对具有不同文件扩展名的 JSON 和类似数据格式:尝试将其解析为 JSON。如果失败,则可能是文件扩展名错误或文件损坏。当然尽量不要让你的服务器在这个过程中被利用,例如通过尝试将 2GB 的 JSON 文件解析到内存中……

标签: php json mime-types


【解决方案1】:

fileinfo 扩展(与file Unix 命令之类的类似工具一样)主要搜索在数据库中定义的签名(称为“魔术”)。如果我没记错的话,PHP 的魔法数据库目前已编译为扩展二进制文件,因此您无法查看它,但您的系统中可能会有类似的数据库。我在C:\Apache24\conf.magic 有 Apache,这是 JPEG 的条目:

# JPEG images
0   beshort     0xffd8      image/jpeg

任何以0xffd8 开头的都是图片。完成!

我对这种格式不是特别熟悉,但它似乎连 look 都不适合 JSON。而且,正如您可能已经猜到的那样,整体实用程序绝不是一项安全功能。它只是一个帮助工具来确定文件可能包含什么。如果例如,这非常方便。您已经从损坏的磁盘中恢复了没有扩展名的文件。


MIME 类型很酷。你设置了application/json,每个人都知道它是 JSON。简单明了,不是吗。只有两个警告:

  • 文件系统(其中许多实际上是在 MIME 类型之前发明的)存储许多文件属性(名称、上次修改日期、权限,有时甚至是图标...),但不存储 MIME 类型。 (当然,可能有一些学术文件系统可以,但不是 FAT32、NTFS、ext4 ......)。它通常不会添加有价值的信息,它是另一个需要保持更新的令牌,而且它特别不便携(将您的文件复制到 U 盘,它们就消失了)。

  • 它仍然不是安全功能。如果我可以伪造文件内容,是什么阻止我伪造 MIME 类型?


那么,你能做什么?最好的选择是:什么都没有。

只需将文件解析为 JSON 并检测它是否失败。无论如何,您都需要这样做,它会告诉您您需要做的一切。 JSON 只是纯文本数据。也许添加一些检查以防止非常大的文件(同样,您应该在文件上传时这样做)并添加$depth 检查,仅此而已。

if (json_decode($s_file_path, true, 32)!==null || json_last_error()!==JSON_ERROR_NONE) {
    // Valid JSON
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 2021-11-15
    • 2012-07-28
    • 2011-09-19
    • 2012-03-31
    • 2017-11-01
    相关资源
    最近更新 更多