为什么php下载停止在大文件上?

时间:2018-02-15 15:48:32

标签: php

我有一个php脚本,允许用户下载大文件。除了超过500mb的文件外,该脚本运行良好。每次我尝试下载一个664mb的文件时,下载停止在460mb左右(大约15-17分钟)。没有错误。我能做什么?一世 怀疑脚本超时,但我不明白为什么。我花了好几天试图让它工作,只是无法取得任何进展。任何想法或建议都会很棒。我正在使用托管服务器,所以不能遗憾地尝试modx_sendfile。我正在使用php 7.0.25

$db = new mysqli($dbHost, $dbUsername, $dbPassword, $dbName);

ob_start() or die('Cannot start output buffering');
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

$strDownloadFolder = "files/";
//- turn off compression on the server
//@apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 'Off');

//Download a file more than once
$boolAllowMultipleDownload = 2;
if(!empty($_GET['key'])){
    //check the DB for the key
    $sql = "SELECT * FROM downloads WHERE downloadkey = '".mysqli_real_escape_string($db,$_GET['key'])."' LIMIT 1";
    $resCheck=mysqli_query($db, $sql);
      $arrCheck = mysqli_fetch_array($resCheck); //Create array from first result
    if(!empty($arrCheck['file'])){
        //check that the download time hasnt expired
        if($arrCheck['expires']>=time()){
            if(!$arrCheck['downloads'] OR $boolAllowMultipleDownload){

                //everything is ok -let the user download it
                $strDownload = $strDownloadFolder.$arrCheck['file'];
                if(file_exists($strDownload)){


$file_path  = $arrCheck['file'];
$path_parts = pathinfo($file_path);
$file_name  = $path_parts['basename'];
$file_ext   = $path_parts['extension'];
$file_path  = 'files/' . $file_name;


// allow a file to be streamed instead of sent as an attachment
$is_attachment = isset($_REQUEST['stream']) ? false : true;

// make sure the file exists
if (is_file($file_path))
{
    $file_size  = filesize($file_path);
    $file = @fopen($file_path,"rb");
    if ($file)
    {
        // set the headers, prevent caching
        header("Pragma: public");
        header("Expires: -1");
        header("Cache-Control: public, must-revalidate, post-check=0, pre-check=0");
        header("Content-Disposition: attachment; filename=\"$file_name\"");

        // set appropriate headers for attachment or streamed file
        if ($is_attachment) {
                header("Content-Disposition: attachment; filename=\"$file_name\"");
        }
        else {
                header('Content-Disposition: inline;');
                header('Content-Transfer-Encoding: binary');
        }

        // set the mime type based on extension, add yours if needed.
        $ctype_default = "application/octet-stream";
        $content_types = array(
                "exe" => "application/octet-stream",
                "zip" => "application/zip",
                "mp3" => "audio/mpeg",
                "mpg" => "video/mpeg",
                "avi" => "video/x-msvideo",
        );
        $ctype = isset($content_types[$file_ext]) ? $content_types[$file_ext] : $ctype_default;
        header("Content-Type: " . $ctype);

        //check if http_range is sent by browser (or download manager)
        if(isset($_SERVER['HTTP_RANGE']))
        {
            list($size_unit, $range_orig) = explode('=', $_SERVER['HTTP_RANGE'], 2);
            if ($size_unit == 'bytes')
            {

                list($range, $extra_ranges) = explode(',', $range_orig, 2);
            }
            else
            {
                $range = '';
                header('HTTP/1.1 416 Requested Range Not Satisfiable');
                exit;
            }
        }
        else
        {
            $range = '';
        }

        //figure out download piece from range (if set)
        list($seek_start, $seek_end) = explode('-', $range, 2);

        //set start and end based on range (if set), else set defaults
        //also check for invalid ranges.
        $seek_end   = (empty($seek_end)) ? ($file_size - 1) : min(abs(intval($seek_end)),($file_size - 1));
        $seek_start = (empty($seek_start) || $seek_end < abs(intval($seek_start))) ? 0 : max(abs(intval($seek_start)),0);

        //Only send partial content header if downloading a piece of the file (IE workaround)
        if ($seek_start > 0 || $seek_end < ($file_size - 1))
        {
            header('HTTP/1.1 206 Partial Content');
            header('Content-Range: bytes '.$seek_start.'-'.$seek_end.'/'.$file_size);
            header('Content-Length: '.($seek_end - $seek_start + 1));
        }
        else
          header("Content-Length: $file_size");

        header('Accept-Ranges: bytes');

        set_time_limit(0);
        fseek($file, $seek_start);

        while(!feof($file)) 
        {
            print(@fread($file, 1024*8));
            ob_flush();
            flush();
            if (connection_status()!=0) 
            {
                @fclose($file);
                exit;
            }           
        }

        // file save was a success
        @fclose($file);
        exit;
    }
    else 
    {
        // file couldn't be opened
        header("HTTP/1.0 500 Internal Server Error");
        exit;
    }
}
else
{
    // file does not exist
    header("HTTP/1.0 404 Not Found");
    exit;
}





                    }else{
                    echo "We couldn't find the file to download.";

                }
            }else{
                //this file has already been downloaded and multiple downloads are not allowed
                echo "This file has already been downloaded.";
            }
        }else{
            //this download has passed its expiry date
            echo "This download has expired.";
        }
    }else{
        //the download key given didnt match anything in the DB
        echo "No file was found to download.";
    }
}else{
    //No download key wa provided to this script
    echo "No download key was provided. Please return to the previous page and try again.";
}

一段更简单的代码仍然会引发同样的问题(但适用于较小的文件)mkaes我认为这是一个托管/ php.ini问题,虽然我不知道为什么。

<?php
$local_file = 'my_big_file.zip';
$download_file = 'my_big_file.zip';

// set the download rate limit (=> 20,5 kb/s)

if(file_exists($local_file) && is_file($local_file))
{
    header('Cache-control: private');
    header('Content-Type: application/octet-stream');
    header('Content-Length: '.filesize($local_file));
    header('Content-Disposition: filename='.$download_file);

    flush();
    $file = fopen($local_file, "r");
    while(!feof($file))
    {
        // send the current file part to the browser
        print fread($file, round(1024 * 1024));
        // flush the content to the browser
        flush();
        // sleep one second
        sleep(1);
    }
    fclose($file);}
else {
    die('Error: The file '.$local_file.' does not exist!');
}

?>

此脚本在大约17分钟后停止下载。

0 个答案:

没有答案