【问题标题】:Download a large XML file from an external source in the background, with the ability to resume download if incomplete在后台从外部源下载大型 XML 文件,如果下载不完整,可以继续下载
【发布时间】:2012-04-30 04:36:42
【问题描述】:

一些背景资料

我要下载的文件会在外部服务器上保存一周,并且每小时都会在那里创建一个具有不同名称的新 XML 文件(10-50mb 大)。我希望每次加载我的网站时在后台将大文件逐块下载到我的服务器上,每次大概 0.5mb,然后在下次其他人加载网站时继续下载。这将要求我的网站每小时至少有 100 个页面加载以保持更新,因此如果可能的话,每次可能会增加更多的文件。我研究过simpleXMLXMLreaderSAX解析,但是无论我做什么,似乎直接解析文件都需要很长时间,因此我想要一种不同的方法,即像上面描述的那样下载它。

如果我下载一个 30mb 大型 XML 文件,我可以在 3 秒内使用 XMLreader 在本地解析它(250k 次迭代),但是当我尝试从外部服务器执行相同操作时,将其限制为50k 次迭代,它使用 15 秒来读取那一小部分,因此似乎无法直接从该服务器解析它。

可能的解决方案

我认为最好使用 cURL。但话又说回来,也许 fopen()fsockopen()copy()file_get_contents() 是要走的路。我正在寻找关于使用哪些函数来实现这一点的建议,或者关于如何将 50mb 外部 XML 文件解析到 mySQL 数据库的不同解决方案。

我怀疑每小时执行一次 Cron 工作是最好的解决方案,但我不确定网络托管公司对它的支持程度如何,我也不知道如何做这样的事情。但如果这是最好的解决方案,而且大多数人都这么认为,我也必须在该领域进行研究。

如果在后台运行的 java applet/javascript 会是一个更好的解决方案,那么当涉及到那里的函数/方法/库时,请指出正确的方向。

总结

  • 在 后台,并在每次加载我的网站时恢复下载 直到完成?
  • 如果即使尝试上述解决方案也很愚蠢,那该怎么办 您会使用语言/软件来实现相同的目标(每小时下载一个大文件)吗?

在此先感谢您的所有回答,对于长篇大论/问题深表歉意。

编辑:我最终使用此解决方案通过 cron 作业调度 php 脚本来获取文件。它检查我的文件夹中已有的文件,生成过去四天可能下载的列表,然后下载下一个 XML 文件。

<?php
$date = new DateTime();
$current_time = $date->getTimestamp();
$four_days_ago = $current_time-345600;

echo 'Downloading: '."\n";
for ($i=$four_days_ago; $i<=$current_time; ) {
    $date->setTimestamp($i);

    if($date->format('H') !== '00') {
        $temp_filename = $date->format('Y_m_d_H') ."_full.xml";
        if(!glob($temp_filename)) {
            $temp_url = 'http://www.external-site-example.com/'.$date->format('Y/m/d/H') .".xml";
            echo $temp_filename.' --- '.$temp_url.'<br>'."\n";
            break; // with a break here, this loop will only return the next file you should download
        }
    }
    $i += 3600;
}

set_time_limit(300);
$Start = getTime(); 

$objInputStream = fopen($temp_url, "rb");
$objTempStream = fopen($temp_filename, "w+b");

stream_copy_to_stream($objInputStream, $objTempStream, (1024*200000));

$End = getTime();
echo '<br>It took '.number_format(($End - $Start),2).' secs to download "'.$temp_filename.'".';

function getTime() {
    $a = explode (' ',microtime());
    return(double) $a[0] + $a[1];
}
?>

edit2:我只是想告诉您,有一种方法可以按照我的要求进行操作,但在我的情况下它不起作用。有了我需要的数据量,网站必须每小时有 400 多个访问者才能正常工作。但是对于较少量的数据,有一些选择; http://www.google.no/search?q=poormanscron

【问题讨论】:

    标签: php file curl stream


    【解决方案1】:

    你可以试试fopen:

    <?php
    $handle = fopen("http://www.example.com/test.xml", "rb");
    $contents = stream_get_contents($handle);
    fclose($handle);
    ?>
    

    【讨论】:

    • 感谢您的回复。该脚本返回 211754 字节,仅此而已。执行时间为 18.41 秒。我不确定“echo $contents;”是否是测试输出的正确方法,因此欢迎提供任何其他信息。
    【解决方案2】:

    您需要有一个计划的离线任务(例如,cronjob)。你所追求的解决方案是完全错误的。

    可能工作的最简单的事情是你每小时运行的一个 php 脚本(很可能是通过 cron 安排的),它会下载文件并处理它。

    【讨论】:

    • 非常感谢您的回复。我以前很怕那个。我真的希望有一个 php 解决方案可以让我阅读例如首先是第一个 200k 字节,下一次它会从字节 200 001 读取到 400 000 等等,等等。但是,如果 cron 计划每小时的 php 脚本是最好的解决方案,那么我想我只需要去买一个托管服务,他们可以提供这样的东西。愚蠢的我如何在几秒钟内通过浏览器将文件下载到我自己的计算机上,但是当一个 php 脚本执行它时,它需要 1-2 分钟。如果情况确实如此,那么 PHP 肯定有改进的余地。
    • 在对 Cron 工作进行了一些小的研究之后,我意识到这是要走的路。感谢您提供非常有用的提示。我希望我有足够的代表/分数来评价这个答案,但遗憾的是我还没有。
    猜你喜欢
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-20
    • 1970-01-01
    相关资源
    最近更新 更多