我已经看到这个问题已经存在于stackoverflow中,但我的问题没有答案。
我有从其他服务器下载的许多文件的目录,我不知道有多少文件,我认为维度可以是1GB,或者100Mb取决于外部服务器。
现在我已经这样做了:
ini_set("memory_limit","10000M");
$directory = "xml_uploads/hotel/";
$xml_files = glob($directory . "*.xml");
foreach($xml_files as $file)
{
$content = file_get_contents($file, true);
$xml = new DOMDocument();
$xml->loadXML($content);
if($xml){
//parse xml and save inside database
}
}
我不知道是否更好的方式在memory_limit中插入一个大数字,因为我不知道相关大小adn如果太大我不想停止我的服务器。 还有另一种解析目录中所有xml文件的方法吗?
由于
答案 0 :(得分:1)
XML解析
目前您正在使用DOMDocument
与file_get_contents
结合使用 - 这意味着您必须首先将巨大的XML文件加载到内存中,并且每当文件大于可用内存时,您将始终达到限制 - 使用下面的解决方案,这不是问题。
如果您关心XML解析代码的内存使用情况,您应该使用pull
解析器 - 它是一种XML解析器,它不会将所有内容加载到内存中,但允许您仅在一次只有一个实体 - 这样内存使用量就很小了。在PHP中,您可以使用XML Reader:
$xml = new XMLReader();
$xml->open("config.xml");
while ($xml->read()) {
switch ($xml->name) {
case "myelem":
...
}
}
大量目录树遍历
当然!有一个DirectoryIterator和RecursiveDirectoryIterator
用法非常相似:
foreach(new DirectoryIterator($directory) as $fileInfo)
{
if($fileInfo->getExtension() !== 'xml') continue;
$content = file_get_contents($fileInfo->getPathname(), true);
...
}
此外,如果您有嵌套的目录结构,则可以使用另一个:
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory)) as $fileInfo)
{
if($fileInfo->getExtension() !== 'xml') continue;
$content = file_get_contents($fileInfo->getPathname(), true);
...
}
请注意,由于此迭代器是递归的,因此我们必须使用RecursiveIteratorIterator
包装它;
这两个都可以从PHP 5开始提供(你真的不应该使用下面的任何东西)
答案 1 :(得分:0)
使用下面的代码,您可以获得要上传的文件大小(在上传之前,您将使用js获得文件大小)然后您可以使用ajax上传文件并相应地调整内存大小。
如果不需要,请删除不需要的代码
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Show File Data</title>
<style type='text/css'>
body {
font-family: sans-serif;
}
</style>
<script type='text/javascript'>
function showFileSize() {
var input, file;
// (Can't use `typeof FileReader === "function"` because apparently
// it comes back as "object" on some browsers. So just see if it's there
// at all.)
if (!window.FileReader) {
bodyAppend("p", "The file API isn't supported on this browser yet.");
return;
}
input = document.getElementById('fileinput');
if (!input) {
bodyAppend("p", "Um, couldn't find the fileinput element.");
}
else if (!input.files) {
bodyAppend("p", "This browser doesn't seem to support the `files` property of file inputs.");
}
else if (!input.files[0]) {
bodyAppend("p", "Please select a file before clicking 'Load'");
}
else {
file = input.files[0];
alert("File " + file.name + " is " + file.size + " bytes in size");
//bodyAppend("p", "File " + file.name + " is " + file.size + " bytes in size");
}
}
function bodyAppend(tagName, innerHTML) {
var elm;
elm = document.createElement(tagName);
elm.innerHTML = innerHTML;
document.body.appendChild(elm);
}
</script>
</head>
<body>
<form action='#' onSubmit="return false;">
<input type='file' id='fileinput'>
<input type='button' id='btnLoad' value='Load' onclick='showFileSize();'>
</form>
</body>
</html>
答案 2 :(得分:0)
Adam的回答已经指出了好的课程,我还有一些提示:
当您执行大量文件和时间/内存消耗时,您无法从浏览器中搜索该脚本。服务器主要具有有限的KeepAlive和Timeout,即使使用1 TB内存也会终止你的脚本。
给你的脚本一个shebang,让它可执行(chmod + x或chmod 700)并从控制台(http://www.php.net/manual/en/features.commandline.usage.php)点击它。
#!/usr/bin/php
<?php
// set memory limit here..
// set time limit:
set_time_limit(0)
// maybe enable garbage collector here
// http://php.net/manual/en/features.gc.php
另见有人遇到类似问题的答案: