php - 使用 http ://location broken 加载数据本地 infile

标签 php mysql file-io load-data-infile

背景: 我将一些网站从共享主机帐户移至 VPS。除了使用来自外部服务器的数据源(即 http://server1.net/getfile.php?f=101 )使用 LOAD DATA LOCAL INFILE 执行查询的 php 代码行外,一切都非常顺利。此代码在共享主机帐户上工作(并且工作了很长时间),但是,此帐户已达到资源限制,尤其是在数据库大小/速度方面。

问题: 从 http://地址下载的带有 LOAD DATA INFILE 的代码在移动到(新的)VPS 后不再工作。

系统和软件: VPS 用作网络服务器,运行 Ubuntu (Ubuntu 14.04) 和 Vesta (0.9.8 (amd64))、apache、nginx、mysql (5.5.44)、app-armor 等。所有这些都是最近安装的,很少更改或没有更改。

从 phpinfo() 输出中选择:

System  Linux MyServer 3.13.0-62-generic #102-Ubuntu SMP Tue Aug 11 14:29:36 UTC 2015 x86_64 
Apache Version  Apache/2.4.7 (Ubuntu) mod_fcgid/2.3.9 PHP/5.5.9-1ubuntu4.11 OpenSSL/1.0.1f 
Server Root     /etc/apache2
PATH    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SERVER_SOFTWARE     Apache/2.4.7 (Ubuntu) mod_fcgid/2.3.9 PHP/5.5.9-1ubuntu4.11 OpenSSL/1.0.1f
allow_url_fopen On  On
allow_url_include   Off
doc_root    no value    
docref_ext  no value
docref_root no value
file_uploads    On
open_basedir    no value
sys_temp_dir    /tmp
upload_tmp_dir  /tmp
user_dir    no value
cURL support    enabled 
mysql
Directive                   Local Value  Master Value
mysql.allow_local_infile    On           On
mysqli
Directive                   Local Value  Master Value
mysqli.allow_local_infile   On           On

来自/etc/mysql/my.cnf 的几行

[client]
loose-local-infile=1
local-infile=1

[mysqld]
basedir=/usr
datadir=/var/lib/mysql
tmpdir=/tmp
local-infile=1

下面的代码在与 phpinfo()

文件相同的目录中运行

测试代码:

$url = "http://myserver.net/x.csv";
$file = "/var/lib/mysql/test2.csv";

$handle = curl_init($url);
curl_setopt($handle,  CURLOPT_RETURNTRANSFER, TRUE);
/* Get the HTML or whatever is linked in $url. */
$response = curl_exec($handle);
/* Check for 404 (file not found). */
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
echo("<br>Http code: ". $httpCode);
curl_close($handle);

echo "<br>Temp_name: ". $_FILES["file"]["tmp_name"];
echo "<br>Host info: " . $conn->host_info . "\n";
echo "<br>Client info: ".mysqli_get_client_info($conn) ."\n";

$conn = mysqli_init();
if (!$conn) {
    die('mysqli_init failed');
}

if (!$conn->options(MYSQLI_OPT_LOCAL_INFILE, true)) {
    die('Setting MYSQLI_OPT_LOCAL_INFILE failed');
}

if (!$conn->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5)) {
    die('Setting MYSQLI_OPT_CONNECT_TIMEOUT failed');
}

if (!$conn->real_connect('localhost','root','pass','database')) {
    die('Connect Error (' . mysqli_connect_errno() . ') '
            . mysqli_connect_error());
}

$conn->query("LOAD DATA INFILE '". $file ."' INTO TABLE x_import (@col1) SET ID = @col1;");
echo("<br>Error file: " . mysqli_error($conn));

$conn->query("LOAD DATA INFILE '". $url ."' INTO TABLE x_import (@col1) SET ID = @col1;");
echo("<br>Error url: " . mysqli_error($conn));

$conn->query("LOAD DATA LOCAL INFILE '". $file ."' INTO TABLE x_import (@col1) SET ID = @col1;");
echo("<br>Error file (LOCAL): " . mysqli_error($conn));

$conn->query("LOAD DATA LOCAL INFILE '". $url ."' INTO TABLE x_import (@col1) SET ID = @col1;");
echo("<br>Error url (LOCAL): " . mysqli_error($conn));

$conn->query("SELECT * INTO OUTFILE 'andreas.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n' FROM x_import;");
echo("<br>Error OutFile: " . mysqli_error($conn));

代码结果:

Http code: 200
Temp_name:
Host info:
Client info: 5.5.44
Error file:
Error url: Can't get stat of '/var/lib/mysql/http:/myserver.net/x.csv' (Errcode: 2)
Error file (LOCAL): File '/var/lib/mysql/test2.csv' not found (Errcode: 13)
Error url (LOCAL): File 'http:/myserver.net/x.csv' not found (Errcode: 2)
Error OutFile: File 'andreas.txt' already exists

PHP 代码使用 root 帐户和 mysql,因此那里有完全访问权限。

第一行sql代码(LOAD DATA INFILE without LOCAL using the local file)正确添加数据库中文件中的数据。

带有 INTO OUTFILE 代码的最后一行在/var/lib/mysql/database/中正确创建了一个文件(第二次给出了已经存在的错误)

从目前的所有研究中我了解到:

  • 错误代码 13 是权限问题。
  • 错误代码 02 是找不到文件。
  • “加载数据”用于数据库服务器上的文件。
  • “LOAD DATA LOCAL”用于客户端上的文件(apache/php 代码)。

我不明白的是为什么在使用 LOCAL 时 URL 中缺少一个/(请参阅代码输出)。我也不明白为什么将 LOCAL 添加到 URL 时会出现错误代码 13(php 在代码的第一部分收到代码 200)。在我看来,由于多种原因,php 和 mysql 都无法查看正确的位置。

下面我将解释我尝试过的许多事情的一些尝试(主要来自本网站上的其他答案):

我已将/var/和/var/lib/的文件权限更改为 755(一次更改为 777),但这并未更改我的测试代码输出。/tmp/已设置为 777。

在 app-armor 中,我将 mysql 更改为提示模式,并尝试在 app-armor (usr.sbin.mysqld) 的 mysql 配置文件中进行一些更改,但两者都没有更改测试代码输出。

有用的文档(但我可能没有完全理解): http://dev.mysql.com/doc/refman/5.5/en/load-data-local.html

我更喜欢使用 LOAD DATA LOCAL,但如果它以任何其他方式工作,我也很高兴。

请帮忙。欢迎提出任何问题和建议。

最佳答案

当我尝试使用 mysql load infile(本地主机和远程数据库上的数据文件和项目)时,我遇到了同样的问题。我使用 php 中的直接 mysql 命令(通过 system 函数)。这是我的代码示例:

system('mysql --local-infile -h '.$host. ' -D '.$dbname.' -u'.$dbuser.' -p'.$password." -e \"LOAD DATA LOCAL INFILE '". $pathToFile . "' INTO TABLE table FIELDS TERMINATED BY ';' (field1, field2, field3)\"");

希望对你有用。

关于php - 使用 http ://location broken 加载数据本地 infile,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32738235/

相关文章:

php 哪里查询不起作用

php - 通过单击链接在 cookie 中设置语言设置

php - SQL 编码问题 (Â)

php - 如何让正则表达式忽略括号之间的所有内容?

javascript - jQuery processData 的 PHP 对应项

php - 如何在 union 上更新

php - 新手 PHP MySQL 问题

sql-server - 在 SQL Server 中查看存储在 Varbinary(MAX) 中的文件

python - 验证文件是否已准备好在 py3k 中读取

android - libGdx 无法在 android 应用程序数据目录中找到文件