php& PDO:占位符导致错误的负载数据流动
我在悖论中度过了最后几个小时。我使用此查询将CSV文件导入数据库。
$query = $this->pdo->prepare('
LOAD DATA LOCAL INFILE
:file
INTO TABLE
product_feeds_raw
FIELDS TERMINATED BY
:fields_terminated_by
OPTIONALLY ENCLOSED BY
:fields_optionally_enclosed_by
LINES TERMINATED BY
:lines_terminated_by
IGNORE 1 LINES
(
`aaa`,
`bbb`
)
SET
task_id = :task_id
');
$params = [
'file' => $this->path_to_file,
'fields_terminated_by' => $fields_terminated_by,
'fields_optionally_enclosed_by' => $fields_optionally_enclosed_by,
'lines_terminated_by' => $lines_terminated_by,
'task_id' => $this->task_id
];
$query->execute($params);
整个文件及其设置(分离器,外壳,线终止等)来自最终用户的基于OAUTH的API。我告诉您这显然我不能相信用户输入,因此我必须使用占位符。
问题在于,PDO逃脱了此类参数的方式是奇怪的。这是用户通过API发送的内容:
'fields_terminated_by' => ';',
'fields_optionally_enclosed_by' => '"',
'lines_terminated_by' => '\n',
本质上,我们具有 “
和\ n
,这对于CSV很常见。我使用这些变量为我的占位符喂食,但PDO将它们转化为以下混乱:
LOAD DATA LOCAL INFILE
'../../myfile.csv'
INTO TABLE
product_feeds_raw
FIELDS TERMINATED BY
';'
OPTIONALLY ENCLOSED BY
'\"' <-------------- WRONG
LINES TERMINATED BY
'\\n' <-------------- WRONG
IGNORE 1 LINES
您可以看到PDO在我的前面添加了不必要的
” 。对于\
“\ n
,变成\\ n
也是如此。结果,MySQL无法导入CSV,因为分界符是不同的。查询应该就是这样:
LOAD DATA LOCAL INFILE
'../../myfile.csv'
INTO TABLE
product_feeds_raw
FIELDS TERMINATED BY
';'
OPTIONALLY ENCLOSED BY
'"' <-------------- CORRECT
LINES TERMINATED BY
'\n' <-------------- CORRECT
IGNORE 1 LINES
我花了几个小时查看其他脚本,但是似乎没有人使用加载数据填充
的占位符。不适合定界数。
我知道我可以简单地摆脱占位符的占位符,而只是在查询中使用变量,但我不喜欢这种方法。此外,我应该依靠定制的逃生来消毒用户输入。
建议?
I spent the last few hours in a paradox. I use this query to import a CSV file into my database.
$query = $this->pdo->prepare('
LOAD DATA LOCAL INFILE
:file
INTO TABLE
product_feeds_raw
FIELDS TERMINATED BY
:fields_terminated_by
OPTIONALLY ENCLOSED BY
:fields_optionally_enclosed_by
LINES TERMINATED BY
:lines_terminated_by
IGNORE 1 LINES
(
`aaa`,
`bbb`
)
SET
task_id = :task_id
');
$params = [
'file' => $this->path_to_file,
'fields_terminated_by' => $fields_terminated_by,
'fields_optionally_enclosed_by' => $fields_optionally_enclosed_by,
'lines_terminated_by' => $lines_terminated_by,
'task_id' => $this->task_id
];
$query->execute($params);
The entire file with its settings (separator, enclosure, line termination etc.) arrives from an OAuth-based API from end-users. I am telling you this to underline that obviously I cannot trust user input hence I must use placeholders.
The problem is that the way PDO escapes such parameters is odd. This is what the user sends via API:
'fields_terminated_by' => ';',
'fields_optionally_enclosed_by' => '"',
'lines_terminated_by' => '\n',
In essence we have ;
"
and \n
which is pretty common for a CSV. I use these variables to feed my placeholders but PDO transforms them into this mess:
LOAD DATA LOCAL INFILE
'../../myfile.csv'
INTO TABLE
product_feeds_raw
FIELDS TERMINATED BY
';'
OPTIONALLY ENCLOSED BY
'\"' <-------------- WRONG
LINES TERMINATED BY
'\\n' <-------------- WRONG
IGNORE 1 LINES
As you can see PDO adds an unnecessary \
in front of my "
. Same goes for \n
that becomes \\n
. As result mysql fails to import the CSV because delimiters are different. The query should have been this:
LOAD DATA LOCAL INFILE
'../../myfile.csv'
INTO TABLE
product_feeds_raw
FIELDS TERMINATED BY
';'
OPTIONALLY ENCLOSED BY
'"' <-------------- CORRECT
LINES TERMINATED BY
'\n' <-------------- CORRECT
IGNORE 1 LINES
I spent hours looking at other scripts but no one seems to use placeholders with LOAD DATA INFILE
. Not for delimeters.
I know I could simply get rid of placeholders for delimiters and just use variables inside the query but I don't like this approach. Moreover I should rely on custom-made escapings to sanitize user-input.
Suggestions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论