导入CSV,排除第一行

4

我现在成功导入了我的csv文件,只有一个问题,如何让导入忽略第一行的数据?员工将上传相同格式的文件,其中第一行是列名。

if (isset($_POST['submit'])) {
    if (is_uploaded_file($_FILES['filename']['tmp_name'])) {
        echo "<h1>" . "File " . $_FILES['filename']['name'] . " uploaded successfully." . "</h1>";
        echo "<h2>Displaying contents:</h2>";
        readfile($_FILES['filename']['tmp_name']);
    }

    //Import uploaded file to Database
    $handle = fopen($_FILES['filename']['tmp_name'], "r");

    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $import = "INSERT into tictoc(employee,taskname,tasktime,sessiontime,sessionstart,sessionend,sessionnotes) values('" . $userinfo['first_name'] . " " . $userinfo['last_name'] . "','$data[0]','$data[1]','$data[2]','$data[3]','$data[4]','$data[5]')";

        mysql_query($import) or die(mysql_error());
    }

    fclose($handle);

    print "Import done";
}

3
你的代码容易受到SQL注入攻击。你应该使用预编译语句,将变量作为参数传递给预编译语句,这些参数不会被解析成SQL语句。如果你不知道我在说什么,或者如何修复它,请阅读Bobby Tables的故事。特别是,上传的文件可能包含会注入到你的INSERT语句中的SQL代码。 - eggyal
8个回答

7

只需设置一个变量$i = 0,然后仅在$i = 1或更高时插入。

if (isset($_POST['submit'])) {
    $i=0; //so we can skip first row

    if (is_uploaded_file($_FILES['filename']['tmp_name'])) {
        echo "<h1>" . "File ". $_FILES['filename']['name'] ." uploaded successfully." . "</h1>";
        echo "<h2>Displaying contents:</h2>";
        readfile($_FILES['filename']['tmp_name']);
    }

    //Import uploaded file to Database
    $handle = fopen($_FILES['filename']['tmp_name'], "r");

    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        if($i>0) {
            $import="INSERT into tictoc(employee,taskname,tasktime,sessiontime,sessionstart,sessionend,sessionnotes) values('".$userinfo['first_name']." ".$userinfo['last_name']."','$data[0]','$data[1]','$data[2]','$data[3]','$data[4]','$data[5]')";

            mysql_query($import) or die(mysql_error());
        }
        $i++;
    }

    fclose($handle);

    print "Import done";
}

第一行包含标题内容 - Hector
1
@Hector 但是你的问题是如何跳过第一行。请查看更新后的答案。 - bretterer
这实际上是一种不好的形式,在循环内部有一个条件检查,而可以通过在循环之前简单地读取一行来处理。没有必要使用计数器或循环条件。 - Kraang Prime

6
您可以简单地使用MySQL的LOAD DATA INFILE命令,这比将CSV解析为PHP,为每个记录构建INSERT语句,将其作为字符串提交给MySQL并让MySQL解析该字符串以进行SQL(存在SQL注入风险)要快得多。更快
LOAD DATA INFILE ? INTO TABLE tictoc
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
IGNORE 1 LINES
(tasktime, sessiontime, sessionstart, sessionend, sessionnotes)
SET employee = ?, taskname = ?

使用PDO:
$dbh = new PDO('mysql:dbname='.$dbname, $username, $password);

if (is_uploaded_file($_FILES['filename']['tmp_name'])) {
  $qry = $dbh->prepare('
    LOAD DATA INFILE :filepath INTO TABLE tictoc
    FIELDS TERMINATED BY \',\' OPTIONALLY ENCLOSED BY \'"\'
    IGNORE 1 LINES
    (tasktime, sessiontime, sessionstart, sessionend, sessionnotes)
    SET employee = :employee, taskname = :taskname
  ');

  $qry->execute(array(
    ':filepath' => $_FILES['filename']['tmp_name'],
    ':employee' => $userinfo['first_name'],
    ':taskname' => $userinfo['last_name']
  ));
}

这不能在客户端计算机上远程使用 PHP。 - aahhaa
@wlin:使用 LOCAL 修饰符。 - eggyal

3
如果你喜欢的话,也许可以采用这种方式:
$i=0;
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
    $i++;
    if($i==1) continue;

    $import="INSERT into tictoc(employee,taskname,tasktime,sessiontime,sessionstart,sessionend,sessionnotes) values('".$userinfo['first_name']." ".$userinfo['last_name']."','$data[0]','$data[1]','$data[2]','$data[3]','$data[4]','$data[5]')";

     mysql_query($import) or die(mysql_error());
}

3

不需要变量。这比较简单。以下是一种只需要最少量外部代码的解决方案,完全可行。尝试将以下代码放入:

$headers = fgetcsv($handle, 1000, ",");

在获取CSV数据的while()循环之前,需要获取标题行,但不将其插入到数据库中。一旦while循环开始,第一行已经被返回,因此不能将其插入到mysql中。此外,似乎还需要标题行,因此这也解决了这个问题。
因此,最终结果如下:
if (isset($_POST['submit'])) {
    if (is_uploaded_file($_FILES['filename']['tmp_name'])) {
        echo "<h1>" . "File " . $_FILES['filename']['name'] . " uploaded successfully." . "</h1>";
        echo "<h2>Displaying contents:</h2>";
        readfile($_FILES['filename']['tmp_name']);
    }

    //Import uploaded file to Database
    $handle = fopen($_FILES['filename']['tmp_name'], "r");

    //Grab the headers before doing insertion
    $headers = fgetcsv($handle, 1000, ",");

    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $import = "INSERT into tictoc(employee,taskname,tasktime,sessiontime,sessionstart,sessionend,sessionnotes) values('" . $userinfo['first_name'] . " " . $userinfo['last_name'] . "','$data[0]','$data[1]','$data[2]','$data[3]','$data[4]','$data[5]')";

        mysql_query($import) or die(mysql_error());
    }

    fclose($handle);

    print "Import done";
}

2
您可以尝试以下方法:
array_shift($data);

2
我已经实现了这段代码并测试过了,我认为它非常有用。
您需要遵循一些规则:
1. 您的 CSV 文件应该与数据库表名相对应(例如,如果数据库表名是 users,则 CSV 应该是 users.csv)。
2. 您的 CSV 文件的第一行应该是数据库表字段名称(例如,Id、name 等),在此之后开始输入数据。
3. 您可以从以下链接下载数据源类:http://code.google.com/p/php-csv-parser/,因为我在代码中需要使用以下代码:require_once 'CSV/DataSource.php';
<?php
ini_set('memory_limit','512M');
$dbhost = "localhost";
$dbname = "excel_import";
$dbuser = "root";
$dbpass = "";

$conn=mysql_connect ($dbhost, $dbuser, $dbpass) or die ("I cannot connect to the database because: " . mysql_error());
mysql_select_db($dbname) or die("Unable to select database because: " . mysql_error());


require_once 'CSV/DataSource.php';


$filename = "users.csv";
$ext = explode(".",$filename);
$path = "uploads/".$filename;

$dbtable = $ext[0];

import_csv($dbtable, $path);


function import_csv($dbtable, $csv_file_name_with_path)
{
    $csv = new File_CSV_DataSource;
    $csv->load($csv_file_name_with_path);

    $csvData = $csv->connect();

    $res='';
    foreach($csvData  as $key)
    {
        $myKey ='';
        $myVal='';
        foreach($key as $k=>$v)
        {
            $myKey .=$k.',';
            $myVal .="'".$v."',";
          }

        $myKey = substr($myKey, 0, -1);
        $myVal = substr($myVal, 0, -1); 
        $query="insert into ".$dbtable." ($myKey)values($myVal)";
        $res=  mysql_query($query);

    }

    if($res ==1)
    {

                echo "record successfully Import.";

    }else{

                echo "record not successfully Import.";
    }
}

1

while循环之前声明一个变量

$row=1;

然后在while循环中加入这个条件

if($row==1){
   $row++; 
   continue;
}

0
if (isset($_POST['submit'])) {
if (is_uploaded_file($_FILES['filename']['tmp_name'])) {
    echo "<h1>" . "File " . $_FILES['filename']['name'] . " uploaded successfully." . "</h1>";
    echo "<h2>Displaying contents:</h2>";
    readfile($_FILES['filename']['tmp_name']);
}

//Import uploaded file to Database
$handle = fopen($_FILES['filename']['tmp_name'], "r");
fgetcsv($handle); //skip the reading of the first line from the csv file

while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
    $import = "INSERT into tictoc(employee,taskname,tasktime,sessiontime,sessionstart,sessionend,sessionnotes) values('" . $userinfo['first_name'] . " " . $userinfo['last_name'] . "','$data[0]','$data[1]','$data[2]','$data[3]','$data[4]','$data[5]')";

    mysql_query($import) or die(mysql_error());
}

fclose($handle);

print "Import done";

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接