如果文件超过5mb,如何停止下载文件?如果我在转移时停止它,文件是否会保存在某个其他临时目录或内存中?我怎么会知道?这是我目前的代码:
$url = 'http://www.spacetelescope.org/static/archives/images/large/heic0601a.jpg';
$file = '../temp/test.jpg';
file_put_contents($file, file_get_contents($url));
答案 0 :(得分:8)
您可以通过多种方式执行此操作,但因为您当前正在使用file_get_contents()
,所以我会这样做:
fopen()
fread()
读取文件并以增量保存 - 这可以让您在超过阈值时跟踪当前大小和投掷错误。这样的事情:
$url = 'http://www.spacetelescope.org/static/archives/images/large/heic0601a.jpg';
$file = '../temp/test.jpg';
$limit = 5 * 1024 * 1024; // 5MB
if (!$rfp = fopen($url, 'r')) {
// error, could not open remote file
}
if (!$lfp = fopen($file, 'w')) {
// error, could not open local file
}
// Check the content-length for exceeding the limit
foreach ($http_response_header as $header) {
if (preg_match('/^\s*content-length\s*:\s*(\d+)\s*$/', $header, $matches)) {
if ($matches[1] > $limit) {
// error, file too large
}
}
}
$downloaded = 0;
while (!feof($rfp) && $downloaded < $limit) {
$chunk = fread($rfp, 8192);
fwrite($lfp, $chunk);
$downloaded += strlen($chunk);
}
if ($downloaded > $limit) {
// error, file too large
unlink($file); // delete local data
} else {
// success
}
注意:在收到任何文件以检查文件是否太大之前检查Content-Length:
标题很有吸引力 - 如果您愿意,您仍然可以执行此操作,但不要相信该值!标头本质上是一个任意值,虽然使用与文件大小不匹配的内容长度会违反协议,但它可能会欺骗系统下载违反规则的文件。即使你确实检查了这个值,你也需要计算字节数。
你也可以通过数据回调使用curl来做这件事,但我认为这是一个不太令人满意的解决方案,主要是因为curl需要一个字符串函数名而不是标准的通用callable
类型,意味着您需要使用全局变量或static
变量才能跟踪下载的内容长度,这两者都不可接受(恕我直言)。
答案 1 :(得分:2)
至于获取网址并限制尺寸,这并不太难......但file_get_contents
不会这样做。您可以fopen
该网址,并在流上使用stream_get_meta_data
来获取有关该流的信息数组。如果我正在阅读example权限(如果传输编码不是“分块”),您会在那里找到Content-Length
标题,它会告诉您文件大小。如果该值已设置且超出限制,则保释。
如果流元数据没有该信息,或者信息表明文件足够小,那么您仍然拥有该流本身;您仍然可以fread
从远程文件fwrite
到本地的文件,直到您全部读取或达到限制。当然,如果你到达那一点,一旦达到极限,文件仍然存在;你必须自己删除它。
答案 2 :(得分:1)
file_get_contents
无法实现这一点 - 您需要使用PHP cURL扩展来获取文件大小。
<?php
$max_length = 5 * 1024 * 1024;
$url = 'http://www.spacetelescope.org/static/archives/images/large/heic0601a.jpg';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$data = curl_exec($ch);
curl_close($ch);
if ($data === false) {
echo 'cURL failed';
exit;
}
$contentLength = 'unknown';
if (preg_match('/Content-Length: (\d+)/', $data, $matches)) {
$contentLength = (int)$matches[1];
}
echo "Content-Length: $contentLength\n";
if ($contentLength > $max_length) {
echo "File is too large\n";
} else {
echo "File size is ok\n";
}
将其全部包含在一个函数中并用它来检查一个URL - 可以跳过任何太大的内容。
<强>缺点:强>
此方法仅在服务器返回Content-Length
标头时有效 - 并非所有服务器都表现良好,并且并非所有服务器都返回正确的长度。
<强>上行:强>
无需下载和写入$max_length
个字节。此方法将更快,资源更少。
修改自:
答案 3 :(得分:1)
这是DaveRandom解决方案沿同一行的变化,但在完全加载之前没有写入文件。
<?php
define('MAXMB', 5);
define('BYTESPERMB', 1048576);
$maxsize = MAXMB * BYTESPERMB;
$handle = fopen("http://www.example.com/", "rb");
$contents = '';
$completed = true;
while (!feof($handle)) {
$chunk = fread($handle, 8192);
$size += strlen($chunk);
if ($size > $maxsize) {
$completed = false;
break;
}
$contents .= $chunk;
}
fclose($handle);
if ($completed) {
// File appears to be completely downloaded so write it --
file_put_contents('path/to/localfile', $contents);
} else {
// It was too big
}