"允许记忆......疲惫不堪"使用readfile时

时间:2015-07-07 19:30:35

标签: php file

我在PHP中创建了一个直到昨天才开始工作的下载脚本。今天我尝试下载其中一个文件,发现它突然停止了工作:

  

PHP致命错误:第52行的E:\ home \ tecnoponta \ web \ aluno \ download.php中允许的内存大小为67108864字节(尝试分配119767041字节)

由于某些原因,PHP试图在内存中分配文件的大小,我不知道为什么。如果文件大小小于内存限制,我可以毫无问题地下载它,问题在于更大的文件。

我知道可以通过增加php.ini中的内存限制甚至在代码上使用ini_set来纠正它,但我想要一种更准确的方法来解决这个问题以及为什么它停止工作的答案。

这是我的代码:

$file = utf8_decode($_GET['d']);

header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename='.$file);
header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');

$file = "uploads/$curso/$file";

ob_clean();
flush();
readfile($file);

echo "<script>window.history.back();</script>";
exit;

4 个答案:

答案 0 :(得分:15)

来自php.net for readfile

  即使发送大文件,

readfile()也不会出现任何内存问题   文件,靠它自己。如果遇到内存不足错误,请确保   使用ob_get_level()关闭输出缓冲。

来自php.net for ob_clean

  

此函数不会像ob_end_clean()那样破坏输出缓冲区   确实

你需要的是:

if (ob_get_level()) {
      ob_end_clean();
    }

另外考虑添加:

header('Content-Length: ' . filesize($file));

答案 1 :(得分:4)

ob级解决方案导致始终为空输出。

此解决方案适用于我:

<div ng-app"myApp" ng-controller="movieCtrl">
      irrelavent html code here
</div>
<script>

var app = angular.module('myApp', []);

app.controller('movieCtrl', function($scope, $http) {
    $scope.$watch('search', function() {
        fetch();
    });

    $scope.search = "tt2975590";

    function fetch() {
        $http.get("http:www.omdbapi.com/?i=" + $scope.search + "&plot=full&r=json")
            .then(function(response) {
                $scope.details = response.data;
            });
    }

    $scope.update = function(movie) {
        $scope.search = movie.Title;
    }
});
</script>

因此使用<?php $myFile = $myPath.$myFileName; if (file_exists($myFile)) { header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.$myFileName.'"'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($myFile)); //alternative for readfile($myFile); $myInputStream = fopen($myFile, 'rb'); $myOutputStream = fopen('php://output', 'wb'); stream_copy_to_stream($myInputStream, $myOutputStream); fclose($myOutputStream); fclose($myInputStream); exit; } else { echo "*** ERROR: File does not exist: ".$myFile; } ?> 代替stream_copy_to_stream()

希望这可以帮到你。

答案 2 :(得分:0)

我这样解决:

if(file_exists($filepath)){

  header('Content-Description: File Transfer');
  header('Content-Type: application/octet-stream');
  header('Content-Disposition: attachment; filename='.basename($filepath));
  header('Content-Transfer-Encoding: binary');
  header('Expires: 0');
  header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
  header('Pragma: public');
  header('Content-Length: ' . filesize($filepath));

  if(ob_get_level()){
     ob_end_clean();
  }

  readfile($filepath);
}

答案 3 :(得分:-3)

文件大小大于php内存限制。

待办事项

ini_set('memory_limit','16M');

并设置&#39; 16M&#39;部分至少是文件大小。