【问题标题】:Remote streaming files larger than 1GB大于 1GB 的远程流媒体文件
【发布时间】:2017-09-05 01:57:17
【问题描述】:

我有一个 PHP 应用程序,它从远程 URL 流式传输文件。

对于小文件,它可以正常工作。但是,当我尝试下载大于1GB 的文件时,它只会读取第一个1GB,然后停止。

fread() 总是返回empty,而feof()true
该文件大于1GB,并且数据仍未读取。

远程使用fread()official documentation不清楚;没看懂。

我使用来自 NextCloud 的代码 https://github.com/nextcloud/server/blob/master/lib/private/Files/Stream/Encryption.php#L457 当 S3 作为主存储时,它通过远程 url 上传和下载。但是这个函数并不总是返回完整的数据。

【问题讨论】:

  • 我们不是通灵者。向我们展示您正在使用的代码。
  • 来自 NextCloud 的更新代码

标签: php fopen fread


【解决方案1】:

通过 http 下载大文件

<?php
function DownloadFile($file){

   //First, see if the file exists
   if (!is_file($file)) { die("<b>404 File not found!</b>"); }

   //Gather relevent info about file
   $len = filesize($file);
   $filename = basename($file);
   $file_extension = strtolower(substr(strrchr($filename,"."),1));

   //This will set the Content-Type to the appropriate setting for the file
   switch( $file_extension ) {
     case "exe": $ctype="application/octet-stream"; break;
     case "zip": $ctype="application/zip"; break;
     case "mp3": $ctype="audio/mpeg"; break;
     case "mpg":$ctype="video/mpeg"; break;
     case "avi": $ctype="video/x-msvideo"; break;

     //The following are for extensions that shouldn't be downloaded (sensitive stuff, like php files)
     case "php":
     case "htm":
     case "html":
     case "txt": die("<b>Cannot be used for ". $file_extension ." files!</b>"); break;

     default: $ctype="application/force-download";
   }

   //Begin writing headers
   header("Pragma: public");
   header("Expires: 0");
   header("Cache-Control:");
   header("Cache-Control: public"); 
   header("Content-Description: File Transfer");

   //Use the switch-generated Content-Type
   header("Content-Type: $ctype");
$filespaces = str_replace("_", " ", $filename);

//if your filename contains underscores, you can replace them with spaces
  $header='Content-Disposition: attachment; filename='.$filespaces.';';
   header($header );
   header("Content-Transfer-Encoding: binary");

      $size=filesize($file);
    //check if http_range is sent by browser (or download manager)
       if(isset($_ENV['HTTP_RANGE'])) {
    list($a, $range)=explode("=",$_ENV['HTTP_RANGE']);
    //if yes, download missing part
    str_replace($range, "-", $range);
    $size2=$size-1;
    header("Content-Range: $range$size2/$size");
    $new_length=$size2-$range;
    header("Content-Length: $new_length");
    /if not, download whole file
    } else {
    $size2=$size-1;
    header("Content-Range: bytes 0-$size2/$size");
    header("Content-Length: ".$size2);
    }
    //open the file
    $fp=fopen("$file","r");
    //seek to start of missing part
    fseek($fp,$range);
    //start buffered download
    while(!feof($fp))
    {
    //reset time limit for big files
    set_time_limit();
    print(fread($fp,1024*8));
    flush();
    }
    fclose($fp); 

   exit;

} 
?>

用法:

<?php
    DownloadFile("somefile.mp3");
?>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-12
    相关资源
    最近更新 更多