繁体   English   中英

使用file_get_contents和curl作为文件大小

[英]Using file_get_contents vs curl for file size

我在服务器上运行了一个文件上传脚本,该脚本还具有远程上传功能。一切正常,但是我想知道通过URL进行上传的最佳方法是什么。 现在,我正在使用fopen从粘贴在名为“ from”的文本框中的远程URL获取文件。 我听说fopen不是最好的方法。 这是为什么?

另外,我正在使用file_get_contents从URL获取文件的文件大小。 我听说curl在那部分上更好。 为什么会这样,以及如何将这些更改应用于此脚本?

<?php
$from = htmlspecialchars(trim($_POST['from']));

if ($from != "") {
    $file = file_get_contents($from);
    $filesize = strlen($file);

    while (!feof($file)) {
        $move = "./uploads/" . $rand2;
        move_upload($_FILES['from']['tmp_name'], $move);

        $newfile = fopen("./uploads/" . $rand2, "wb");
        file_put_contents($newfile, $file);
    }
}
?>

您可以使用filesize获取磁盘上文件的文件大小。

file_get_contents实际上将文件存入内存,因此$filesize = strlen(file_get_contents($from)); 已经获取了文件,除了找到文件大小外,您什么都不做。 您可以用fwrite代替file_put_contents ;

请参阅: file_get_contentsfile_put_contents

当您需要更多访问HTTP协议时,可以使用curl 在PHP中使用curl StackOverflow上有很多问题和示例。

因此,我们可以首先下载文件,在本示例中,我将使用file_get_contents ,获取其大小,然后将文件放在本地磁盘上的目录中。

$tmpFile = file_get_contents($from);
$fileSize = strlen($tmpFile);
// you could do a check for file size here
$newFileName = "./uploads/$rand2";
file_put_contents($newFileName, $tmpFile);

在您的代码中,您具有move_upload($_FILES['from']['tmp_name'], $move); 但是$_FILES仅在您具有<input type="file">元素(似乎没有)时才适用。

PS您可能应该在文件名中允许白名单的字符,例如$goodFilename = preg_replace("/^[^a-zA-Z0-9]+$/", "-", $filename)这通常更容易阅读和更安全。

更换:

while (!feof($file)) {
    $move = "./uploads/" . $rand2;
    move_upload($_FILES['from']['tmp_name'], $move);

    $newfile = fopen("./uploads/" . $rand2, "wb");
    file_put_contents($newfile, $file);
}

带有:

$newFile = "./uploads/" . $rand2;
file_put_contents($newfile, $file);

整个文件由file_get_contents读取整个文件由file_put_contents

据我了解您的问题:您想获取URL给出的远程文件的文件大小,并且不确定哪种解决方案是最佳/最快的。

首先,在这种情况下, CURLfile_get_contents()fread()之间的最大区别是CURL和file_get_contents()将整个内容都放入了内存中,而fopen()使您可以更好地控制文件的哪些部分读。 我认为fopen()和file_get_contents()在您的情况下几乎相等,因为您要处理的是小文件,并且您实际上想获取整个文件。 因此,在内存使用方面没有任何区别。

CURL只是file_get_contents()的老大哥。 实际上,它是一个完整的HTTP客户端,而不是某种简单功能的包装器。

关于HTTP:别忘了HTTP除了GET和POST之外还有更多。 你为什么不只是使用资源的元数据,以检查它的大小之前,你甚至得到它? 这是HTTP方法HEAD的目的。 PHP甚至带有用于获取标头的内置函数: get_headers() 但是它有一些缺陷:它仍然发送GET请求,这可能会使它变慢一些,并且它遵循重定向,这可能会导致安全问题。 但是您可以通过调整默认上下文轻松解决此问题:

$opts = array(
    'http' =>
        array(
            'method' => 'HEAD',
            'max_redirects'=> 1,
            'ignore_errors'=> true
        )
);

stream_context_set_default($opts);

做完了 现在,您可以简单地获取标题:

$headers = get_headers('http://example.com/pic.png', 1);

//set the keys to lowercase so we don't have to deal with lower- and upper case
$lowerCaseHeaders = array_change_key_case($headers);

// 'content-length' is the header we're interested in:
$filesize = $lowerCaseHeaders['content-length'];

注: filesize() 不会对HTTP / HTTPS流包装工作,因为统计()不支持( http://php.net/manual/en/wrappers.http.php )。

就是这样。 当然,如果您更喜欢CURL,也可以轻松实现 方法将是相同的(将标头变红)。

以下是使用CURL获取文件及其大小(下载后)的方法:

// Create a CURL handle
$ch = curl_init();

// Set all the options on this handle
// find a full list on 
// http://au2.php.net/manual/en/curl.constants.php
// http://us2.php.net/manual/en/function.curl-setopt.php (for actual usage)
curl_setopt($ch, CURLOPT_URL, 'http://example.com/pic.png');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

// Send the request and store what is returned to a variable
// This actually contains the raw image data now, you could
// pass it to e.g. file_put_contents();
$data = curl_exec($ch);

// get the required info about the request
// find a full list on
// http://us2.php.net/manual/en/function.curl-getinfo.php
$filesize = curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD);

// close the handle after you're done
curl_close($ch);

纯PHP方法: http : //codepad.viper-7.com/p8mlOt

使用CURL: http//codepad.viper-7.com/uWmsYB

对于格式良好且易于阅读的文件大小的输出,我从Laravel中学到了这个惊人的功能:

function get_file_size($size)
{
  $units = array('Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB');
  return @round($size / pow(1024, ($i = floor(log($size, 1024)))), 2).' '.$units[$i];
}

如果您不想处理所有这些,则应查看Guzzle 对于任何种类的HTTP东西,它都是一个非常强大且非常易于使用的库。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM