• 0 رای - 0 میانگین
  • 1
  • 2
  • 3
  • 4
  • 5
اجازه دانلود به کاربران vip در سرور دانلود (بدون mysql)
#1
Question 
با سلام
خسته نباشین

دوستان یک سایت فروش فایل داریم که روی سرور یک قرار داره. این سایت فایل های خودش رو در سرور 2 که مخصوص دانلوده و بدون mysql هست قرار میده. حالا با کمک php و htaccess کاری کردم که هر کاربر برای دانلود یک فایل خاص (مثلا abc.mp4)، یک لینک یکتا داشته باشه و نباید بتونه با آدرس اصلی فایل، اون رو دانلود کنه. (مثال زیر)

کاربر یک: http://example.com/files/abc.mp4 <----- http://example.com/er3457h.mp4
کاربر دو: http://example.com/files/abc.mp4 <----- http://example.com/3Rg4tre.mp4
کاربر سه: http://example.com/files/abc.mp4 <----- http://example.com/zf4tYjK.mp4

مشکلی که الان درگیرش هستم اینه که وقتی کاربر در سرور 2 می خواد فایل رو دانلود کنه، اگر برای انجام دانلود از تابع readfile استفاده کنم، بدلیل اینکه حجم فایل ها بیشتر از 500 مگابایت هست، اگر تعداد زیادی به سرور متصل بشن، دچار کمبود رم خواهیم شد و سرور دان میشه. روش های زیادی هم مثل بافر و ... تست کردم فرقی نکرد. متاسفانه روش x-sendfile بدلیل اینکه امکان فعالسازیش روی سرور 2 نیست قابل اجرا نیست.

دوستان کسی میتونه راهنمایی کنه؟
راهی نداره که بشه با php و htaccess به روش http فایل رو دانلود کنیم تا رم مصرف نشه؟

متاسفانه روش های زیر مناسب نبودن


نمونه کد (1) برای دانلود در سرور دو:
کد پی‌اچ‌پی:
header("Content-Type: video/mp4");
readfile("./files/abc.mp4"); 


نمونه کد (2) برای دانلود در سرور دو:
کد پی‌اچ‌پی:
function resumableDownload($file,$filename,$file_size,$content_type,$disposition 'inline')
{
    @
set_time_limit(0);
    
session_write_close();
    
// turn off compression on the server
    
@ini_set('zlib.output_compression''Off');
    
    
$time filemtime($file);
    
$etag md5($file.$time);
    
    
$fileopen fopen($file"rb");
    
// Download speed in KB/s
    
$chunk 8*1024;
    
// Initialize the range of bytes to be transferred
    
$start 0;
    
$end $file_size-1;
    
// Check HTTP_RANGE variable
    
if (
        isset(
$_SERVER
        && 
preg_match('/^bytes=(\d+)-(\d*)/'$_SERVER$arr)
    )
    {
        
$start $arr;
        if (
$arr) {
            
$end $arr;
        }
    }
    
// Check if starting and ending byte is valid
    
if ($start $end || $start $file_size-1) {
    
header("HTTP/1.1 416 Requested Range Not Satisfiable");
    
header("Content-Length: 0");
    return 
false;
    } else {
    
// For the first time download
    
if ($start == && $end == $file_size) {
    
// Send HTTP OK header
    
header("HTTP/1.1 200 OK");
    } else {
    
// For resume download
    
header("HTTP/1.1 206 Partial Content");
    
header("Content-Range: bytes ".$start."-".$end."/".$file_size);
    }
    
// Bytes left
    
$left $end-$start+1;
    
    
//set last-modified header
    
header('Last-Modified: '.date('D, d M Y H:i:s \G\M\T'$time));
    
//set etag-header
    
header('ETag: "'.$etag.'"');
    
    
// Send the other headers
    
header("Accept-Ranges: bytes");
    
header("Content-Length: ".$left);
    
header("Content-Type: $content_type");
    
header("Content-Disposition: $disposition; filename=\"".$filename."\"");
    
header("Content-Transfer-Encoding: binary");
    
header("Expires: -1");
    
// Read file from the given starting bytes
    
fseek($fileopen$start);
    
    while (!
feof($fileopen)) {
    echo 
fread($fileopen$chunk);
    @
ob_flush();
    
flush();
    
$left-=$chunk;
    
// // Delay for 10 microsecond
    // usleep(10);
    
}
    }
    
fclose($fileopen);
    return 
true;
}

resumableDownload("./files/abc.mp4" "abc.mp4" sizeof("./files/abc.mp4") , "video/mp4" 'inline'); 


نمونه کد (3) برای دانلود در سرور دو:
کد پی‌اچ‌پی:
function download_file($file,$ctype$is_resume=TRUE)
{
    
//First, see if the file exists
    
if (!is_file($file))
    {
        die(
"<b>404 File not found!</b>");
    }
    
//Gather relevent info about file
    
$size filesize($file);
    
$fileinfo pathinfo($file);
    
//workaround for IE filename bug with multiple periods / multiple dots in filename
    //that adds square brackets to filename - eg. setup.abc.exe becomes setup[1].abc.exe
    
$filename = (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) ?
        
preg_replace('/\./''%2e'$fileinfo['basename'], substr_count($fileinfo['basename'], '.') - 1) :
        
$fileinfo['basename'];
    
//check if http_range is sent by browser (or download manager)
    
if($is_resume && isset($_SERVER['HTTP_RANGE']))
    {
        list(
$size_unit$range_orig) = explode('='$_SERVER['HTTP_RANGE'], 2);
        if (
$size_unit == 'bytes')
        {
            
//multiple ranges could be specified at the same time, but for simplicity only serve the first range
            //http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt
            
list($range$extra_ranges) = explode(','$range_orig2);
        }
        else
        {
            
$range '';
        }
    }
    else
    {
        
$range '';
    }
    
//figure out download piece from range (if set)
    
list($seek_start$seek_end) = explode('-'$range2);
    
//set start and end based on range (if set), else set defaults
    //also check for invalid ranges.
    
$seek_end = (empty($seek_end)) ? ($size 1) : min(abs(intval($seek_end)),($size 1));
    
$seek_start = (empty($seek_start) || $seek_end abs(intval($seek_start))) ? max(abs(intval($seek_start)),0);
    
//add headers if resumable
    
if ($is_resume)
    {
        
//Only send partial content header if downloading a piece of the file (IE workaround)
        
if ($seek_start || $seek_end < ($size 1))
        {
            
header('HTTP/1.1 206 Partial Content');
        }
        
header('Accept-Ranges: bytes');
        
header('Content-Range: bytes '.$seek_start.'-'.$seek_end.'/'.$size);
    }
    
//headers for IE Bugs (is this necessary?)
    //header("Cache-Control: cache, must-revalidate");
    //header("Pragma: public");
    
header('Content-Type: ' $ctype);
    
header('Content-Disposition: attachment; filename="' $filename '"');
    
header('Content-Length: '.($seek_end $seek_start 1));
    
//open the file
    
$fp fopen($file'rb');
    
//seek to start of missing part
    
fseek($fp$seek_start);
    
//start buffered download
    
while(!feof($fp))
    {
        
//reset time limit for big files
        
set_time_limit(0);
        print(
fread($fp1024*8));
        
flush();
        
ob_flush();
    }
    
fclose($fp);
    exit;
}

download_file("./files/abc.mp4""video/mp4" TRUE); 


نمونه کد (4) برای دانلود در سرور دو:
کد پی‌اچ‌پی:
function dl_file_resumable($file$is_resume=TRUE)
{

    
//First, see if the file exists

    
if (!is_file($file))

    {

        die(
"<b>404 File not found!</b>");

    }



    
//Gather relevent info about file

    
$size filesize($file);

    
$fileinfo pathinfo($file);



    
//workaround for IE filename bug with multiple periods / multiple dots in filename

    //that adds square brackets to filename - eg. setup.abc.exe becomes setup[1].abc.exe

    
$filename = (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) ?

                
preg_replace('/\./''%2e'$fileinfo['basename'], substr_count($fileinfo['basename'], '.') - 1) :

                
$fileinfo['basename'];



    
$file_extension strtolower($path_info['extension']);



    
//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;

        case 
'mp4'$ctype='video/mp4'; break;

        default:    
$ctype='application/force-download';

    }



    
//check if http_range is sent by browser (or download manager)

    
if($is_resume && isset($_SERVER['HTTP_RANGE']))

    {

        list(
$size_unit$range_orig) = explode('='$_SERVER['HTTP_RANGE'], 2);



        if (
$size_unit == 'bytes')

        {

            
//multiple ranges could be specified at the same time, but for simplicity only serve the first range

            //http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt

            
list($range$extra_ranges) = explode(','$range_orig2);

        }

        else

        {

            
$range '';

        }

    }

    else

    {

        
$range '';

    }



    
//figure out download piece from range (if set)

    
list($seek_start$seek_end) = explode('-'$range2);



    
//set start and end based on range (if set), else set defaults

    //also check for invalid ranges.

    
$seek_end = (empty($seek_end)) ? ($size 1) : min(abs(intval($seek_end)),($size 1));

    
$seek_start = (empty($seek_start) || $seek_end abs(intval($seek_start))) ? max(abs(intval($seek_start)),0);



    
//add headers if resumable

    
if ($is_resume)

    {

        
//Only send partial content header if downloading a piece of the file (IE workaround)

        
if ($seek_start || $seek_end < ($size 1))

        {

            
header('HTTP/1.1 206 Partial Content');

        }



        
header('Accept-Ranges: bytes');

        
header('Content-Range: bytes '.$seek_start.'-'.$seek_end.'/'.$size);

    }



    
//headers for IE Bugs (is this necessary?)

    //header("Cache-Control: cache, must-revalidate");  

    //header("Pragma: public");



    
header('Content-Type: ' $ctype);

    
header('Content-Disposition: attachment; filename="' $filename '"');

    
header('Content-Length: '.($seek_end $seek_start 1));



    
//open the file

    
$fp fopen($file'rb');

    
//seek to start of missing part

    
fseek($fp$seek_start);



    
//start buffered download

    
while(!feof($fp))

    {

        
//reset time limit for big files

        
set_time_limit(0);

        print(
fread($fp1024*8));

        
flush();

        
ob_flush();

    }



    
fclose($fp);

    exit;

}

dl_file_resumable("./files/abc.mp4"TRUE); 


نمونه کد (5) برای دانلود در سرور دو:
کد پی‌اچ‌پی:
function download_from_server($sysfile)
{
    
//$sysfile = '/var/www/html/myfile';
    
if(file_exists($sysfile)) {
        
header('Content-Description: File Transfer');
        
header('Content-Type: application/octet-stream');
        
//header('Content-Disposition: attachment; filename="mytitle"');
        
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($sysfile));
        
ob_clean();
        
ob_end_flush();
        
$handle fopen($sysfile"rb");
        while (!
feof($handle)) {
            echo 
fread($handle1000);
        }
    }
}

download_from_server("./files/abc.mp4"); 




نمونه کد (6) برای دانلود در سرور دو:
کد پی‌اچ‌پی:
function readfile_chunked($filename$retbytes TRUE) {
    
$buffer "";
    
$cnt =0;
    
// $handle = fopen($filename, "rb");
    
$handle fopen($filename"rb");
    if (
$handle === false) {
    return 
false;
    }
    while (!
feof($handle)) {
    
$buffer fread($handleCHUNK_SIZE);
    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;
}

define("CHUNK_SIZE"1024*1024); // Size (in bytes) of tiles chunk
$filename "./files/abc.mp4";
$mimetype "video/mp4";
header("Content-Type: ".$mimetype );
readfile_chunked($filename); 
  پاسخ
تشکر شده توسط :
#2
سلام دوست گرامی. شما نباید همه ی فایل رو بافر کنید و به خروجی بفرستید. میتونید فایل رو به صورت مولتی پارت (چند تکه ای) تبدیل کنید و اون رو به کلاینت ارسال کنید.
میتونید از دستور Readfile استفاده کنید و فایل رو با طول های 20 کیلو بایت بخونید و به کلاینت استفاده کنید در این صورت رم شما اگه 2 گیگ باشه تقسیم بر 20 کیلوبایت که بکنید تعداد کاربرانی که همزمان میتونن از روی سرور شما دانلود کنن بدست میاد.
امیدوارم که متوجه شده باشید. موفق باشید. (طرح چه-tarhche)
  پاسخ
تشکر شده توسط : mghhgm
#3
(۱۳۹۶ مرداد ۱۹, ۰۹:۱۲ ق.ظ)mahdikhanzadi نوشته: سلام دوست گرامی. شما نباید همه ی فایل رو بافر کنید و به خروجی بفرستید. میتونید فایل رو به صورت مولتی پارت (چند تکه ای) تبدیل کنید و اون رو به کلاینت ارسال کنید.
میتونید از دستور Readfile استفاده کنید و فایل رو با طول های 20 کیلو بایت بخونید و به کلاینت استفاده کنید در این صورت رم شما اگه 2 گیگ باشه تقسیم بر 20 کیلوبایت که بکنید تعداد کاربرانی که همزمان میتونن از روی سرور شما دانلود کنن بدست میاد.
امیدوارم که متوجه شده باشید. موفق باشید. (طرح چه-tarhche)

سلام دوست عزیز با این روش مشکلی که پیش میاد، سرعت دانلود هر کاربر 20 کیلوبایت بر ثانیه خواهد بود.
  پاسخ
تشکر شده توسط : Alaa


پرش به انجمن:


کاربران در حال بازدید این موضوع: 1 مهمان