Jump to content

PHP download timeouts.

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
4 replies to this topic

#1
fannypack

fannypack

    Newbie

  • Members
  • Pip
  • 3 posts
I'm using a download script for my simplemachines forum but the problem is it's using read_chunk and the file I am offering to my visits is around 900mb. I'm having trouble determining if the script is just failing, or my host has effectively negated my ability to offer files in such a way. The download stops about midway through the transfer (400mb or so) Here is the code:
<?php

    /**********************************************\

    | SMFSHOP (Shop MOD for Simple Machines Forum) |

    | (c) 2005 DanSoft Australia |

    |  |

    \**********************************************/

     

    //File: filedownload2.php

    // File Download Item

     

    //VERSION: 1.2 (Build 5) --Fixed v1

    //DATE: 15th April 2006

     

    class item_filedownload2 extends itemTemplate {


    function getItemDetails() {

     

    $this->name = "Download xxx File v2";

    $this->desc = "Download a file [INSERT FILE DESCRIPTION HERE]";

    $this->price = 200;


    $this->require_input = false;

    $this->can_use_item = true;

    }


    //see AddToPostCount for more info

    function getAddInput() {

    return "File Name: <input type='text' name='info1' value='file_name_here.txt' size='60'><br>

    This file name does NOT need to be the same name as the file on the server. This name

    is what the file will be saved as on the user's computer.<br><br>

    File Path (INCLUDING FILE NAME): <input type='text' name='info2' value='../../file_name_here.txt' size='60'><br>

    <b>IMPORTANT: </b>Make SURE that this file path is <b>OUT of your webroot.</b> If your forum is

    stored at /home/myuser/public_html/forum/ then store the downloadable file at

    /home/myuser/files/ or similar. Otherwise, you run the risk of the file being

    downloaded without being paid for.<br>

    <input type='checkbox' name='info3'>Delete item from inventory after use";

    }

     

    function onUse() {

    global $item_info, $db_prefix;

    header("Content-type: application/octet-stream");

    header("Content-Disposition: attachment; filename={$item_info[1]}");

    readfile_chunked($item_info[2], false);


    if (isset($item_info[3]) && $item_info[3] = "on") {

    $result = db_query("DELETE FROM {$db_prefix}shop_inventory

    WHERE id = {$_GET['id']}",

    __FILE__, __LINE__);

    }

    exit();

     

    }

    }


    function readfile_chunked($filename,$retbytes=true) {

    $chunksize = 1*(1024*1024); // how many bytes per chunk
    $buffer = '';
    $cnt =0;
    // $handle = fopen($filename, 'rb');
    $handle = fopen($filename, 'rb');
    if ($handle === false) {
    return false;
    }

    while (!feof($handle)) {

    $buffer = fread($handle, $chunksize);
    echo $buffer;

    ob_flush();

    flush();

    if ($retbytes) {

    $cnt += strlen($buffer);

    }

    }

    $status = fclose($handle);

    if ($retbytes && $status) {

    return $cnt; // return num. bytes delivered like readfile() does.

    }

    return $status;

    }

     

     

?>

What I am trying to do is have this script simply handle the download by sending the link directly, with no chunking, so that my download has resume support, etc.

Thank you.

#2
Guest_Jordan_*

Guest_Jordan_*
  • Guests
Do you know your max execution time? You can write a little script to show you using http://us3.php.net/m...on.ini-get.php:

<?php
echo ini_get('max_exeuction_time');

You can also change your execution time using PHP: set_time_limit - Manual

This will not work on PHP in Safe Mode. Another option, instead of chunking the file to the user, would be to simply forward them to the file location using the header directives. This would make the HTTP server responsible for sending the data instead of your PHP script. The one drawback to this method is that certain files will not be "forced" download such as .html file or .pdf file (which will load in the bowser instead) .

#3
fannypack

fannypack

    Newbie

  • Members
  • Pip
  • 3 posts
While retaining the original code that I have there, to also remove the item from the database once it has been clicked, how would I go about doing what you suggested by letting the server handle the download? This is what I'm after, but I'm kind of an idiot.

#4
fannypack

fannypack

    Newbie

  • Members
  • Pip
  • 3 posts
Someone made a suggestion somewhere else to me to use header("Location: path"); but I don't know how to use it in the context of replacing the Content-Disposition that is currently there. Would I need to remove the read_chunk portion of code? I'm pretty naive when it comes to programming but this is essential for my site to function. I mean if someone here wants a few bucks for helping me with this I'll gladly send it.

The script is setup so that when I download the file it removes the item from the database so the user cannot click the link again, all that stuff is there and works fine, I just want to change how the download is processed. This is what I'm trying but it doesn't work

    function onUse() {
$handle = fopen($filename, 'rb');
    global $item_info, $db_prefix;

    header("Content-type: application/octet-stream");

    header("Location: /archives/$filename");

    


    

    $result = db_query("DELETE FROM {$db_prefix}shop_inventory

    WHERE id = {$_GET['id']}",

    __FILE__, __LINE__);

Then when I click download it just sends me to mysite.com/archives

#5
Guest_Jordan_*

Guest_Jordan_*
  • Guests
You need to remove the fopen() portion as well, it is no longer needed if you are simply using header() to forward your users. It looks like you've modified your script properly above. I would prefix the path with your URL (http://www.yourdomai...hives/$filename). Does $filename actually contain a value when passed to the function?