繁体   English   中英

使用 PHP 将 CSV 文件上传到 SQL 服务器时出现问题

[英]Problems with uploading CSV file to SQL Server with PHP

我创建了一个 web 应用程序,以允许用户将CSV文件上传到 SQL 服务器。 我总共有 8 列。 SQL 服务器中的 id 列是自动递增的,因此减去该列。 上传成功,但是每列导入的数据都是null 此外,我的CSV中的记录数少于 100 条,但我的 SQL 服务器显示导入的记录超过 100 条,这些记录不相符。 任何人都可以帮助检查我的代码有什么问题吗?

下面是我的代码和我的 CSV 文件和 SQL 服务器表的屏幕截图。

<?php

$self = $_SERVER['PHP_SELF'];
$request = $_SERVER['REQUEST_METHOD'];

if (!isset($_GET['success'])) {
$get_success = "";
}
else {
$get_success = $_GET['success'];
}

if (!empty($_FILES)) { 

    /* Format the errors and die */
    
    function get_last_error() {
        $retErrors = sqlsrv_errors(SQLSRV_ERR_ALL);
        $errorMessage = 'No errors found';

        if ($retErrors != null) {
            $errorMessage = '';

            foreach ($retErrors as $arrError) {
                $errorMessage .= "SQLState: ".$arrError['SQLSTATE']."<br>\n";
                $errorMessage .= "Error Code: ".$arrError['code']."<br>\n";
                $errorMessage .= "Message: ".$arrError['message']."<br>\n";
            }
        }

        die ($errorMessage);
    }

    /* connect */
    function connect() {
        if (!function_exists('sqlsrv_num_rows')) { // Insure sqlsrv_1.1 is loaded.
            die ('sqlsrv_1.1 is not available');
        }

        /* Log all Errors */
        sqlsrv_configure("WarningsReturnAsErrors", TRUE);        // BE SURE TO NOT ERROR ON A WARNING
        sqlsrv_configure("LogSubsystems", SQLSRV_LOG_SYSTEM_ALL);
        sqlsrv_configure("LogSeverity", SQLSRV_LOG_SEVERITY_ALL);

        $conn = sqlsrv_connect('servername', array
        (
        'UID' => '',
        'PWD' => '',
        'Database' => 'databasename',
        'CharacterSet' => 'UTF-8',
        'MultipleActiveResultSets' => true,
        'ConnectionPooling' => true,
        'ReturnDatesAsStrings' => true,
        ));

        if ($conn === FALSE) {
            get_last_error();
        }

        return $conn;
    }

    function query($conn, $query) {
        $result = sqlsrv_query($conn, $query);
        if ($result === FALSE) {
            get_last_error();
        }
        return $result;
    }

    /* Prepare a reusable query (prepare/execute) */
    
    function prepare ( $conn, $query, $params ) {
        $result = sqlsrv_prepare($conn, $query, $params);
        if ($result === FALSE) {
            get_last_error();
        }
        return $result;
    }

    /*
    do the deed. once prepared, execute can be called multiple times
    getting different values from the variable references.
    */
    
    function execute ( $stmt ) {
        $result = sqlsrv_execute($stmt);
        if ($result === FALSE) {
            get_last_error();
        }
        return $result;
    }

    function fetch_array($query) {
        $result = sqlsrv_fetch_array($query, SQLSRV_FETCH_ASSOC);
        if ($result === FALSE) {
            get_last_error();
        }
        return $result;
    }

    $conn = connect();

    /* prepare the statement */
    $query = "INSERT TABLEName values ( ? , ? , ? , ?, ?, ?, ?, ?)";
    $param1 = null; // this will hold col1 from the CSV
    $param2 = null; // this will hold col2 from the CSV
    $param3 = null; // this will hold col3 from the CSV
    $param4 = null; // this will hold col4 from the CSV
    $param5 = null; // this will hold col5 from the CSV
    $param6 = null; // this will hold col6 from the CSV
    $param7 = null; // this will hold col7 from the CSV
    $param8 = null; // this will hold col8 from the CSV
    $params = array( $param1, $param2, $param3, $param4, $param5, $param6, $param7, $param8 );
    $prep = prepare ( $conn, $query, $params );
    //$result = execute ( $prep );

    //get the csv file 
    
    $file = $_FILES["csv"]["tmp_name"]; 
    
  /*
    Here is where you read in and parse your CSV file into an array.
    That may get too large, so you would have to read smaller chunks of rows.
  */
  
    $csv_array = file($file);
    foreach ($csv_array as $row_num => $row) {
        $row = trim ($row);
        $column = explode ( ',' , $row );
        $param1 = $column[0];
        $param2 = $column[1];
        $param3 = $column[2];
        $param4 = $column[3];
        $param5 = $column[4];
        $param6 = $column[5];
        $param7 = $column[6];
        $param8 = $column[7];
        // insert the row
        
        $result = execute ( $prep );
    }
    
/* Free statement and connection resources. */

sqlsrv_close($conn);
header( "Location: uploadcsv.php?success=1" );
}

?>


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>CSV Upload</title>
</head>
<body>
<?php if (!empty($get_success)) { echo "<b>Your file has been imported.</b><br><br>"; } //generic success notice ?> 

<form action="" method="post" enctype="multipart/form-data" name="uploadcsv" id="uploadcsv"> 
  Upload a CSV file from your computer: <br /> 
  <input name="csv" type="file" id="csv" /> 
  <input type="submit" name="Submit" value="Submit" /> 
</form> 


<body>
</html>

CSV数据文件

CSV

sqlserver 表

在此处输入图像描述

贴出的代码有两个主要问题:

  1. CSV 数据未正确读取,并且
  2. 提供给prepare()$params数组未正确更新。

问题 1:读取 CSV。

您正在使用 PHP 的file()方法来读取 CSV 文件。

如果您尝试逐行解析 CSV 文件,然后用逗号分隔行,那么您做错了。 阅读RFC 4180 Common Format and MIME Type for Comma-Separated Values (CSV) Files ,了解 CSV 文件的结构,并注意字段数据可以包含逗号、引号和换行符。 即:您需要一个面向字符的 state 机器来解析它们。

正确的方法是使用 CSV 解析 function 或其他人已经为您编写和调试的库,例如: fgestcsv()

考虑以下示例...

foo1.csv:

col1,col2,col3
alpha,bravo,charlie
"hello,
""cruel""
world!",bravo,charlie

foo1.php:

<?php
if (($handle = fopen("foo1.csv", "r")) !== FALSE) {
    $row = 1;
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        print "Row $row: ";
        var_dump($data);
        $row++;
    }
    fclose($handle);
}
?>

运行此输出时...

% php -f foo1.php
Row 1: array(3) {
  [0]=>
  string(4) "col1"
  [1]=>
  string(4) "col2"
  [2]=>
  string(4) "col3"
}
Row 2: array(3) {
  [0]=>
  string(5) "alpha"
  [1]=>
  string(5) "bravo"
  [2]=>
  string(7) "charlie"
}
Row 3: array(3) {
  [0]=>
  string(19) "hello,
"cruel"
world!"
  [1]=>
  string(5) "bravo"
  [2]=>
  string(7) "charlie"
}

问题 2:正确更新 $params

发布的代码从变量构造一个数组,然后使用 CSV 数据更新变量。 这不起作用,请考虑以下...

foo2.php:

<?php
$param1 = null;
print "\$param1 = ";
var_dump($param1);

$params = array($param1);
print "\$params = ";
var_dump($params);

$param1 = 42;
print "\$param1 = ";
var_dump($param1);
print "\$params = ";
var_dump($params);

$params[0] = 47;
print "\$params = ";
var_dump($params);
?>

运行此输出时...

% php -f foo2.php
$param1 = NULL
$params = array(1) {
  [0]=>
  NULL
}
$param1 = int(42)
$params = array(1) {
  [0]=>
  NULL
}
$params = array(1) {
  [0]=>
  int(47)
}

请注意$param1如何成功更新为 42 但$params[0]仍然是 NULL? $params仅在我们直接通过$params[0]设置应用时才更新。

您的 CSV 读取代码(希望更新为使用 fgestcsv())应该直接更新$params[0]$params[7]数组元素。

我还创建了一个非常简单的 PHP 模块,其中,我将 CSV 文件从目录上传到 MySql 你可以在这里查看,

https://github.com/Anmolhive/PHP-CSV-Upload/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM