Php 验证CSV文件是否确实是CSV文件

Php 验证CSV文件是否确实是CSV文件,php,regex,file-upload,csv,Php,Regex,File Upload,Csv,我想确保我们的一个客户上传的CSV文件在PHP中确实是一个CSV文件。我很好地处理了上传本身。我并不担心恶意用户,但我担心的是那些试图上传Excel工作簿的用户。除非我弄错了,否则Excel工作簿和CSV仍然可以有相同的MIME,所以检查这还不够好 是否有一个正则表达式可以验证CSV文件是否真的是CSV文件?(我不需要解析……这就是PHP的fgetcsv()的用途。)我见过好几种,但它们后面通常会有类似“它不适用于案例X”的注释 还有其他更好的处理方法吗 (我希望CSV包含名字/姓氏、部门名称…

我想确保我们的一个客户上传的CSV文件在PHP中确实是一个CSV文件。我很好地处理了上传本身。我并不担心恶意用户,但我担心的是那些试图上传Excel工作簿的用户。除非我弄错了,否则Excel工作簿和CSV仍然可以有相同的MIME,所以检查这还不够好

是否有一个正则表达式可以验证CSV文件是否真的是CSV文件?(我不需要解析……这就是PHP的fgetcsv()的用途。)我见过好几种,但它们后面通常会有类似“它不适用于案例X”的注释

还有其他更好的处理方法吗


(我希望CSV包含名字/姓氏、部门名称……没什么特别的。)

您可以编写一个RE,让您猜测该文件是否为有效的CSV,但也许更好的方法是尝试将该文件作为CSV进行解析(使用fgetcsv()调用),如果调用失败,则假定该文件无效


换句话说,查看该文件是否为有效的CSV文件的最佳方法是尝试将其解析为有效的CSV文件,并假设如果解析失败,则该文件不是CSV

最简单的方法是尝试解析CSV并尝试从中读取值。使用
str_getcsv
解析它,然后尝试从中读取值。如果您能够读取并验证至少两个值,则CSV是有效的

编辑

如果您无权访问
str_getcsv
,请使用此选项,作为
str_getcsv
的替换项,从以下位置:


与其他文件格式不同,CSV在文件头中没有指示字节。它直接从实际数据开始

除了实际解析它,并计算结果中是否有预期的列数,我看不到任何方法


只要读取确定第一行所需的字符就足够了(=直到第一行中断)。

从技术上讲,几乎任何文本文件都可以是CSV文件(不匹配的引号除外,等等)。您可以尝试猜测它是否是二进制文件,但除非您的数据只有ASCII或类似类型的内容,否则没有可靠的方法来猜测。如果您所关心的只是人们没有错误地上传Excel文件,请检查文件扩展名。

任何文本文件都是有效文件,因此无法找到验证其正确性的标准方法,因为这取决于您真正期望的文件名

在开始之前,您必须知道该文件中使用了什么分隔符。之后,最简单的验证方法是使用函数。例如:

<?php
$row = 1;
if (($handle = fopen("test.csv", "r")) !== FALSE) {
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $num = count($data); // Number of fields in a row.
        if ($num !== 5)
        {
            // OMG! Column count is not five!
        }
        else if (intval($data[$c]) == 0)
        {
            // OMG! Customer thinks we sold a car for $0!
        }
    }
    fclose($handle);
}
?>


Excel工作簿不是有一个神奇的数字吗?我很幸运,使用Web平台安装程序在IIS上运行PHP,并且只有5.2.0版,而不是5.3版。我没有提到那件事。但是,这并不能阻止我将fgetcsv()与文件处理程序一起使用,每次只能使用一行。我遇到了同样的问题。。有关解决方案,请参阅我编辑的文章。请参阅。几乎所有文本都是某种形式的“有效CSV”。要判断它是否有意义,最好的方法是查找正确数量的字段、正确的标题等。这意味着解析。呃,我想当我说“解析”时,我想我不会依赖正则表达式来放置任何匹配到变量中的内容。@Guttsy任何地方都没有正则表达式。我正在检查fgetcsv()读入Excel工作簿时将返回false,但至少在EOF之前不会返回。编写严格处理哪怕是一行CSV的RE非常棘手,如果允许字段溢出多行,则更是如此。结论是正确的,尽管-解析CSV以确保它是CSV。显而易见的解决方案是显而易见的。。。我喜欢。我只是检查一下分机,因为我怀疑我们的任何客户都不会介意作弊。
<?php
$row = 1;
if (($handle = fopen("test.csv", "r")) !== FALSE) {
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $num = count($data); // Number of fields in a row.
        if ($num !== 5)
        {
            // OMG! Column count is not five!
        }
        else if (intval($data[$c]) == 0)
        {
            // OMG! Customer thinks we sold a car for $0!
        }
    }
    fclose($handle);
}
?>