Php 如果文件大于给定大小,则阻止从远程源加载

Php 如果文件大于给定大小,则阻止从远程源加载,php,domdocument,filesize,Php,Domdocument,Filesize,比方说,我希望从远程服务器加载最多10MB的XML文件 差不多 $xml_file = "http://example.com/largeXML.xml";// size= 500MB //PRACTICAL EXAMPLE: $xml_file = "http://www.cs.washington.edu/research/xmldatasets/data/pir/psd7003.xml";// size= 683MB /*GOAL: Do anything that can be d

比方说,我希望从远程服务器加载最多10MB的XML文件

差不多

$xml_file = "http://example.com/largeXML.xml";// size= 500MB

//PRACTICAL EXAMPLE: $xml_file = "http://www.cs.washington.edu/research/xmldatasets/data/pir/psd7003.xml";// size= 683MB

 /*GOAL: Do anything that can be done to hinder this large file from being loaded by the DOMDocument without having to load the File n check*/

$dom =  new DOMDocument();

$dom->load($xml_file /*LOAD only IF the file_size is <= 10MB....else...echo 'File is too large'*/);
var_dump(
    curl_get_file_size(
        "http://www.dailymotion.com/rss/user/dialhainaut/"
    )
);
我得到
字符串“未知”(长度=7)

当我尝试使用下面建议的
get_headers
时,标题中缺少内容长度,因此这也无法可靠地工作


请告知如何确定
长度
,如果长度超过
10MB,请避免将其发送到
DOMDocument
,编辑:新答案有点变通方法:
您不能检查Dom元素的长度,但可以发出头请求并从URL获取文件大小:

<?php

function i_hope_this_works( $XmlUrl ) {
    //lets assume we fk up so we set size to -1  
    $size = -1;

      $request = curl_init( $XmlUrl );

      // Go for a head request, so the body of a 1 gb file will take the same as 1 kb
      curl_setopt( $request, CURLOPT_NOBODY, true );
      curl_setopt( $request, CURLOPT_HEADER, true );
      curl_setopt( $request, CURLOPT_RETURNTRANSFER, true );
      curl_setopt( $request, CURLOPT_FOLLOWLOCATION, true );
      curl_setopt( $request, CURLOPT_USERAGENT, get_user_agent_string() );

      $requesteddata = curl_exec( $request );
      curl_close( $request );

      if( $requesteddata ) {
        $content_length = "unknown";
        $status = "unknown";

        if( preg_match( "/^HTTP\/1\.[01] (\d\d\d)/", $requesteddata, $matches ) ) {
          $status = (int)$matches[1];
        }

        if( preg_match( "/Content-Length: (\d+)/", $requesteddata, $matches ) ) {
          $content_length = (int)$matches[1];
        }

        // you can google status qoutes 200 is Ok for example
        if( $status == 200 || ($status > 300 && $status <= 308) ) {
          $result = $content_length;
        }
      }

      return $result;
    }
    ?>

10MB等于10485760 B。如果未指定内容长度,则将使用自php5起可用的卷曲。我从某处得到这个消息来源,但我记不起来了

function get_filesize($url) {
    $headers = get_headers($url, 1);
    if (isset($headers['Content-Length'])) return $headers['Content-Length'];
    if (isset($headers['Content-length'])) return $headers['Content-length'];
    $c = curl_init();
    curl_setopt_array($c, array(
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => array('User-Agent: Mozilla/5.0 
         (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.3) 
          Gecko/20090824 Firefox/3.5.3'),
        ));
    curl_exec($c);
    return curl_getinfo($c, CURLINFO_SIZE_DOWNLOAD);
    }
}
    $filesize = get_filesize("http://www.dailymotion.com/rss/user/dialhainaut/");
    if($filesize<=10485760){
        echo 'Fine';
    }else{
       echo $filesize.'File is too big';
    }    
函数get_filesize($url){ $headers=get_headers($url,1); if(isset($headers['Content-Length'])返回$headers['Content-Length']; if(isset($headers['Content-length'])返回$headers['Content-length']; $c=curl_init(); curl_setopt_数组($c,数组)( CURLOPT_URL=>$URL, CURLOPT_RETURNTRANSFER=>true, CURLOPT_HTTPHEADER=>array('User-Agent:Mozilla/5.0 (麦金塔;美国;英特尔Mac OS X 10.5;欧洲;rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3', )); 首席执行官(c美元); 返回curl\u getinfo($c,CURLINFO\u SIZE\u下载); } } $filesize=获取文件大小(“http://www.dailymotion.com/rss/user/dialhainaut/");
如果($filesizeOk,终于起作用了。headers解决方案显然不能广泛地起作用。在这个解决方案中,我们打开一个文件句柄,逐行读取XML,直到它达到$max_B的阈值。如果文件太大,我们仍然有读到10MB标记的开销,但它可以按预期工作。如果文件小于$max_B,继续

$xml_file = "http://www.dailymotion.com/rss/user/dialhainaut/";
//$xml_file = "http://www.cs.washington.edu/research/xmldatasets/data/pir/psd7003.xml";

$fh = fopen($xml_file, "r");  

if($fh){
    $file_string = '';
    $total_B = 0;
    $max_B = 10485760;
    //run through lines of the file, concatenating them into a string
    while (!feof($fh)){
        if($line = fgets($fh)){
            $total_B += strlen($line);
            if($total_B < $max_B){
                $file_string .= $line;
            } else {
                break;
            }
        }
    } 

    if($total_B < $max_B){
        echo 'File ok. Total size = '.$total_B.' bytes. Proceeding...';
        //proceed
        $dom = new DOMDocument();
        $dom->loadXML($file_string); //NOTE the method change because we're loading from a string   

    } else {
        //reject
        echo 'File too big! Max size = '.$max_B.' bytes.';  
    }

    fclose($fh);

} else {
    echo '404 file not found!';
}
$xml\u文件=”http://www.dailymotion.com/rss/user/dialhainaut/";
//$xml_文件=”http://www.cs.washington.edu/research/xmldatasets/data/pir/psd7003.xml";
$fh=fopen($xml_文件,“r”);
若有($fh){
$file_string='';
$total_B=0;
$max_B=10485760;
//遍历文件的行,将它们连接成字符串
而(!feof($fh)){
如果($line=fgets($fh)){
$total_B+=斯特伦(行);
如果($total_B<$max_B){
$file_string.=$line;
}否则{
打破
}
}
} 
如果($total_B<$max_B){
echo“文件正常。总大小=”.$Total_B.“字节。正在进行…”;
//进行
$dom=新的DOMDocument();
$dom->loadXML($file_string);//注意方法的更改,因为我们是从字符串加载的
}否则{
//拒绝
echo“文件太大!最大大小=”.$Max_B.“字节”;
}
fclose($fh);
}否则{
echo“找不到404文件!”;
}

你看过函数了吗?@MawiaHL你能试试吗:
var\u dump(filesize(“http://www.cs.washington.edu/research/xmldatasets/data/pir/psd7003.xml“”)
Page not found是结果。@MawiaHL--这将在浏览器中加载:……但不适用于
var\u dump(filesize)中的
filesize()
('https://www.w3.org/TR/2001/REC-xsl-20011015/xslspec.xml'))
@downvorters….请告知问题的症结所在。谢谢!结果:
警告:第5行的C:\…\fileSize\u tst\index.php中的字符串偏移量'size'非法。
大小的值是什么?大小未知……可以是任何大小……但不能是
>10MB
。文件来自远程服务器。。(请再读一题)我的意思是变量中有什么size@johannes--文件未被
上载
它已上载到其他服务器的某个位置,我们只想使用
DOMDocument
读取它,但我们想停止读取…或…**根本不读取**如果其大小超过
10MB
…即:像:
http://www.cs.washington.edu/research/xmldatasets/data/pir/psd7003.xmlhttp://www.cs.washington.edu/research/xmldatasets/data/SwissProt/SwissProt.xml
你太过分了large@MawaiHL--我们已经尝试过了,在它在这个XML上使用失败之前:
$head=array\u change\u key\u case(get\u headers("http://www.dailymotion.com/rss/user/dialhainaut/“,TRUE”);
标题不包括
内容长度
…请尝试通知。Thx@ErickBest, ‌​ut/不返回任何内容。它只返回
页面未找到您要查找的页面受限制或不存在
。因此,当文件根本不存在时,如何知道文件的大小。--请在Web浏览器中尝试此操作:@Mawia HL…是的…已确认…,工作正常…(希望我能有两个可接受的答案)@ErickBest,使用我的答案比使用公认答案的优势在于,某些主机提供程序禁用了fopen()函数。在Windows Web服务器上,当使用fopen并将文件路径存储在变量中时,如果变量未以ASCII编码,PHP将返回错误。当使用SSL时,Microsoft IIS将违反协议,关闭连接而不发送close_notify指示符。因此Curl更好。使用:
file_get_Content测试时会崩溃新界北http://www.cs.washington.edu/research/xmldatasets/data/pir/psd7003.xml");size//683MB
…善意地建议Script Hanged必须重新启动服务器…
文件获取内容
试图在其正常工作之前将整个
683MB
加载到内存中。是的,我们正在与单个变量的最大大小发生冲突。这是php.ini中的
内存限制设置。我们需要一个更好的解决方案-一个这可以在不加载整个内容的情况下测试文件。太棒了!感谢您的挑战-这肯定是当今最有趣的问题。我仍然会检查标题是否在那里,因为如果在那里,这将为我们节省潜在的麻烦
$xml_file = "http://www.dailymotion.com/rss/user/dialhainaut/";
//$xml_file = "http://www.cs.washington.edu/research/xmldatasets/data/pir/psd7003.xml";

$fh = fopen($xml_file, "r");  

if($fh){
    $file_string = '';
    $total_B = 0;
    $max_B = 10485760;
    //run through lines of the file, concatenating them into a string
    while (!feof($fh)){
        if($line = fgets($fh)){
            $total_B += strlen($line);
            if($total_B < $max_B){
                $file_string .= $line;
            } else {
                break;
            }
        }
    } 

    if($total_B < $max_B){
        echo 'File ok. Total size = '.$total_B.' bytes. Proceeding...';
        //proceed
        $dom = new DOMDocument();
        $dom->loadXML($file_string); //NOTE the method change because we're loading from a string   

    } else {
        //reject
        echo 'File too big! Max size = '.$max_B.' bytes.';  
    }

    fclose($fh);

} else {
    echo '404 file not found!';
}