Comment forcer le téléchargement de gros fichiers sans utiliser trop de mémoire?

Je suis en train de servir de grandes des fichiers zip pour les utilisateurs. Quand il y a 2 connexions simultanées, le serveur est à court de mémoire vive (RAM). J'ai augmenté la quantité de mémoire à partir de 300 MO à 4 go (Dreamhost VPS) et puis il a bien fonctionné.

J'ai besoin pour permettre à beaucoup plus de 2 connexions simultanées. La réelle 4 GO permettrait à quelque chose comme 20 connexions simultanées (trop mal).

Bien, le code actuel, je suis à l'aide, a besoin du double de mémoire, puis la taille réelle du fichier. C'est trop mauvais. Je veux quelque chose comme "streaming" le fichier à l'utilisateur. Donc, je n'accorderai pas plus que le morceau d'être transmis aux utilisateurs.

Le code suivant est celui que j'utilise dans CodeIgniter (framework PHP):

ini_set('memory_limit', '300M'); //it was the maximum amount of memory from my server
set_time_limit(0); //to avoid the connection being terminated by the server when serving bad connection downloads
force_download("download.zip", file_get_contents("../downloads/big_file_80M.zip"));exit;

La force_download fonction est la suivante (CodeIgniter par défaut de la fonction d'assistance):

function force_download($filename = '', $data = '')
{
    if ($filename == '' OR $data == '')
    {
        return FALSE;
    }

    //Try to determine if the filename includes a file extension.
    //We need it in order to set the MIME type
    if (FALSE === strpos($filename, '.'))
    {
        return FALSE;
    }

    //Grab the file extension
    $x = explode('.', $filename);
    $extension = end($x);

    //Load the mime types
    @include(APPPATH.'config/mimes'.EXT);

    //Set a default mime if we can't find it
    if ( ! isset($mimes[$extension]))
    {
        $mime = 'application/octet-stream';
    }
    else
    {
        $mime = (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension];
    }

    //Generate the server headers
    if (strpos($_SERVER['HTTP_USER_AGENT'], "MSIE") !== FALSE)
    {
        header('Content-Type: "'.$mime.'"');
        header('Content-Disposition: attachment; filename="'.$filename.'"');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header("Content-Transfer-Encoding: binary");
        header('Pragma: public');
        header("Content-Length: ".strlen($data));
    }
    else
    {
        header('Content-Type: "'.$mime.'"');
        header('Content-Disposition: attachment; filename="'.$filename.'"');
        header("Content-Transfer-Encoding: binary");
        header('Expires: 0');
        header('Pragma: no-cache');
        header("Content-Length: ".strlen($data));
    }

    exit($data);
}

J'ai essayé quelques morceau codes que j'ai trouvé dans Google, mais le fichier était toujours livré endommagé. Probablement à cause du mauvais code.

Quelqu'un pourrait-il m'aider?

Avez-vous essayé de rediriger vers un fichier à l'aide de l'en-tête Location?
Me semble que vous êtes beaucoup mieux simplement en offrant aux utilisateurs un lien direct vers les fichiers...
J'ai oublié de dire que les fichiers sont dans un dossier n'est pas accessible via le web. C'est pour des raisons de sécurité. Je viens de servir le fichier si l'utilisateur passe à un processus d'authentification. Je vais essayer les suggestions ci-dessous et nous reviendrons à voter pour la meilleure réponse.
Merci pour le texte de révision, @p.campbell je pense que j'étais trop fatigué la nuit dernière... 🙂

OriginalL'auteur Leandro Alves | 2011-06-01