چهارشنبه ۰۸ بهمن ۱۴۰۴

Wednesday, January 28, 2026 GMT +3:30

محدود کردن لینک دانلود مستقیم فایل ها با PHP و htaccess

php-htaccess-download

همان طور که می دانیم، لینک دانلود یک فایل در وب به طور کلی به دو دسته مستقیم و غیر مستقیم تقسیم می شود، منظور از لینک های مستقیم مواردی هستند که عموما به فرمت فایل مورد نظر (به فرض zip.) ختم شده و با کلیک بر روی آنها یا وارد کردن آدرس در مرورگر، بلافاصله برای دانلود ارائه می شوند، قاعدتا تعریف و استفاده از این نوع لینک ها خیلی سخت و پیچیده نیست، اما مشکل اکثر مدیران سایت های مختلف که عمدتا نیاز به محدود کردن دانلود فایل ها یا دانلود با پرداخت هزینه و... دارند، ایجاد و مدیریت نوع دوم از لینک ها یعنی لینک های دانلود غیر مستقیم است، در این حالت کاربر با وارد کردن آدرس لینک در مرورگر (در پس زمینه و در سرور) به صفحه دیگری ارجاع داده شده و به طور مثال ابتدا وضعیت عضویت یا پرداخت هزینه دانلود لینک بررسی و سپس مجوز دسترسی (یا عدم دسترسی) به او داده می شود، از این رو در این مطلب قصد داریم نحوه انجام این کار را با استفاده از PHP و htaccess آموزش دهیم، به این امید که مفید واقع شود.

دستور htaccess برای جلوگیری از دانلود مستقیم


اگر با فایل htaccess. آشنا باشید، می دانید که با استفاده از آن می توان تنظیمات متفاوتی در سرورهای لینوکس و ویندوز (در صورت پیکره بندی مناسب) اعمال کرد که یکی از این تنظیمات، بررسی لینک درخواستی و محدود کردن حالت دانلود مستقیم آن است، در این شیوه در مرحله اول دستوری در htaccess، با استفاده از الگوی عبارات با قاعده فرمت فایل درخواستی را بررسی کرده، اگر فرمت مورد نظر جزء مواردی باشد که نمی خواهیم به صورت مستقیم دریافت شوند، آن را به صورت پارامتر به یک فایل PHP ارسال می کنیم (این کار در سرور و بدون اطلاع کاربر انجام می شود)، به نمونه زیر توجه کنید.
RewriteEngine on
RewriteRule ^file/([^/]+)(\.zip|\.pdf|\.jpg)$ /limit-direct-access/file/download.php?file=$1$2 [NC,L]
در این مثال ساده، در ریشه یا همان root سایت دایرکتوری با نام فرضی limit-direct-access ساخته ایم که درون آن یک فایل htaccess. با دستورات بالا قرار دارد، همچنین یک فولدر با نام file که درون آن فایل download.php به همراه سایر فایل های آماده برای دانلود جای گرفته اند (با دقت به قسمت دوم دستور RewriteRule، درک ترتیب قرار گرفتن فولدرها ساده می شود)، لذا در حالت عادی کاربر برای دانلود فایل فرضی test.zip از دایرکتوری file باید نمونه لینک زیر را از سرور درخواست کند:
http://localhost/limit-direct-access/file/test.zip
اما با توجه به دستور RewriteRule نوشته شده، کاربر بدون اینکه متوجه شود، لینک زیر را از سرور درخواست خواهد کرد:
http://localhost/limit-direct-access/file/download.php?file=test.zip
در واقع لینک اصلی برای سرور مفهوم لینک Rewrite شده را دارد.

بررسی مجوزها و ارسال فایل برای دانلود با PHP


قسمت اول کار که تغییر مسیر لینک کاربر از حالت مستقیم به غیر مستقیم بود به درستی انجام شد! حال نوبت PHP است که کار بررسی مجوزهای ورود، پرداخت و... را انجام دهد و در صورتی که شرایط باب طبع ما باشد، فایل را به مرورگر جهت دانلود ارسال کند، به نمونه زیر توجه کنید.
<?php
@$file_name = $_GET['file'];
//echo $file_name;

//بررسی مجوزهای کاربر
//تعیین نحوه بررسی مجوزها با توجه به برنامه و هدف شما می تواند متفاوت باشد، به طور مثال ممکن است هنگامی که کاربر مبلغ لینک را پرداخت کرده و تراکنش موفقیت آمیز باشد، ضمن نگهداری اطلاعات در دیتابیس جهت استفاده های بعدی، یک سشن آی دی تنظیم کنید، اکنون در هنگام دانلود می توان آن سشن آی دی را بررسی کرد و اگر تنظیم شده باشد، اجازه دسترسی به کاربر داد، یا برای کاربران وارد شده به سایت از همین شیوه می توان استفاده نمود.
$user_access = TRUE;

//کاربر مجاز به دانلود است
if($user_access == TRUE){
    //تابع برای بدست آوردن پسوند فایل
    function getExtension($file){
        preg_match('/\.[^\.]+$/i', $file, $ext);
        return $ext[0];
    }
    
    //نوع فایل    
    $file_type = NULL;
    switch(getExtension($file_name)){
        case 'zip':
        $file_type = 'application/zip';
        break;
        case 'pdf':
        $file_type = 'application/pdf';
        break;
        case 'jpg':
        $file_type = 'image/jpeg';
        break;                
    }
    
    //ارسال فایل به مرورگر برای دانلود
    ob_start();
    header('Content-Description: File Transfer');
    //header('Content-Type: application/octet-stream');    
    header('Content-Type: '.$file_type);
    header('Content-Disposition: attachment; filename='.$file_name);
    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("$file_name"));
    ob_clean();
    flush();
    readfile("$file_name");
    exit;
}
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>وبگو | محدود کردن دسترسی مستقیم به لینک دانلود</title>
<!-- https://webgoo.ir -->
</head>
<body>
<?php
//کاربر مجاز به دانلود نیست
if($user_access == FALSE){
    echo 'Error!';    
}
?>
</body>
</html>
توضیح:
- همان طور که گفتیم نام فایل به صورت یک پارامتر و از طریق متد GET به فایل PHP ارسال می شود، بنابراین در خط اول متغیر file_name را با این روش مقداردهی می کنیم (که برابر با مقادیر دریافتی از پارامتر file است).
- در گام بعدی نیاز به بررسی مجوز دانلود کاربر است، نحوه انجام این مرحله کاملا دلخواه بوده و بستگی به هدف شما دارد، آنچه برای ما اهمیت دارد، مقداردهی متغیر user_access به صورت TRUE یا FALSE است، به طور مثال می توانید برای کاربرانی که تراکنش آنها موفقیت آمیز باشد، یک سشن آی دی تنظیم کنید یا فیلدی را در دیتابیس به صورت حالت پرداخت تعریف کرده و با تطبیق اطلاعات (نام کاربری و کلمه عبور)، وضعیت مجوز دانلود کاربر را بررسی کنید، در هر صورت از هر روشی که استفاده کنید نهایتا باید به نتیجه TRUE یا FALSE ختم شود، لطفا به جهت مفصل بودن این مبحث، در این رابطه به آموزش های سشن و نحوه ایجاد سیستم ورود و خروج سایت مراجعه کنید.
- پس از تعیین حالت TRUE یا FALSE برای متغیر user_access، در صورتی که مقدار TRUE باشد، یعنی کاربر مجاز به دانلود بوده و لذا باید فایل را به مرورگر ارسال کنیم، بدین منظور هم می توانید از دستور زیر برای تعیین نوع MIME فایل استفاده کنید.
header('Content-Type: application/octet-stream');
این دستور به صورت کلی است و برای اکثر فایل ها کاربرد دارد، هم می توانید به صورت اختصاصی نوع MIME فایل ها را با تابع getExtension و دستور switch مشخص کنید (این کار در نمونه کد آموزش حاضر انجام شده است).
نکته: MIME یک استاندارد تعریف شده در وب برای تعیین فایل های مختلف از نظر نوع است که می توانید لیستی از آنها را در لینک زیر مشاهده کنید.
لیست فرمت ها و معادل آنها در استاندارد MIME
- دستورات header که در ادامه تنظیم شده اند برای ارسال صحیح فایل به مرورگر و رعایت استانداردهای HTTP لازم هستند.
- تابع ob_clean و flush برای مدیریت بهتر نقل و انتقال اطلاعات و پاک کردن موارد اضافی از سرور است (ضروری نیست).
- در نهایت نیز تابع readfile فایل مورد نظر را به مرورگر ارسال کرده و دستور exit باعث پایان اجرای کدها می شود.
نکته 1: در صورتی که مقدار متغیر user_access برابر FALSE باشد، بخش دوم دستورات اجرا شده و پیغام Error نمایش داده می شود.
نکته 2: دقت کنید که به دلیل استفاده شدن از توابع header در کد، نباید قبل از اجرای این توابع هیچ نوع خروجی به مرورگر ارسال شود، این خروجی می تواند شامل BOM یا Byte Order Mark نیز شود، لذا باید مطمئن شوید که فایل PHP شما بدون BOM است که بدین منظور می توانید از برنامه Adobe Dreamweaver یا ++Notepad استفاده کرده و BOM را با ذخیره مجدد فایل حذف کنید (در نرم افزار ++Notepad باید از منوی Encoding و امکان Convert to UTF-8 without BOM استفاده کنید).

دانلود نمونه فایل های آموزش


دانلود نمونه فایل های آموزش محدود کردن  لینک دانلود مستقیم فایل ها با PHP و htaccess
دسته بندی: آموزش کاربردی » PHP
related مطالب بیشتر:
نمایش آمار بازدیدها با PHP بدون استفاده از دیتابیس
تبدیل تاریخ میلادی، شمسی با مبدل JDF در PHP
نمایش قسمتی از متن و پاراگراف با PHP
ارسال ایمیل با PHP و کلاس PHPMailer
نحوه نمایش متن و تصاویر اتفاقی در PHP و MySQL
دیدگاه
more ۱۳۵ دیدگاه برای این مطلب ارسال شده است.
more چینش دیدگاه ها به ترتیب از جدیدترین به قدیمی ترین است.
سینا
۱۴:۲۸ ۱۴۰۱/۰۷/۰۲
با تشکر از شما
کدها رو امتحان کردم، با وجودی که
!empty($LimitSystemLogin)
چک میشه ولی واسه همه ارور میده!
بصورت مسدودی سراسری عمل میکنه و به هیچ کسی اجازه ورود نمیده، چه دستگاه تعریف شده داشته باشه و چه نداشته باشه!
اول باید ببینید آرایه شما به درستی ایجاد شده یا خیر، در گام دوم ممکن است عبارت بررسی شده واقعا در اطلاعات تمام سیستم ها موجود باشد و در نتیجه دسترسی برای همه آنها مسدود می شود، نمونه کد پاسخ قبلی مشکلی ندارد و با اطلاعات اولیه درست کار می کند که می توانید واسط کاربری فرضی تنظیم و امتحان کنید.
سینا
۱۳:۳۵ ۱۴۰۱/۰۷/۰۲
با تشکر از شما استاد بزرگوارم
حق با شماست من این کار رو واسه این میخوام که اگر اتفاقی کسی رمز و پسورد کاربری رو هم داشت نتونه وارد پنل کاربریش بشه، وگرنه رمز کاربران دست هر کسی قرار داده نمی شه، حتی نام کاربری ها هم محافظت شده هستند، واسه محکم کاری میخوام اینکار انجام بشه و به قول شما اگه اطلاعات یوزرایجنت رو هم ویرایش کنن نمی دونن من چه چیزی رو برای ورود تعریف کردم! که این اطلاعات هر روز بررسی و بروز میشه، بر اساس ای پی نمیشد اینکارو کرد چون آی پی های ما استاتیک نیستند و با اتصال به اینترنت تغییر می کنند.
از لطف و محبت شما بسیار ممنون و سپاسگزارم
خدا پشت و پناه شما باشه و بهتون سلامتی و عزت بده
خواهش، ممنون از نظر لطف و محبت شما.
سینا
۰۴:۵۶ ۱۴۰۱/۰۷/۰۲
با سلام مجدد
توضیح کدهایی که براتون فرستادم:
الان این کدها دستگاههایی که از روی یوزرایجنت تعریف می کنم همه رو مسدود می کنه و بهشون اجازه ورود نمیده!
من برعکس اینکارو میخوام، یعنی رشته هایی که وارد کردم فقط اجازه ورود داشته باشند.
من میخوام فرضا وقتی اتفاقی کسی نام کاربری و رمز عبور یه نفر رو هم داشت چون مشخصات دستگاهش رو تعریف نکردم اجازه ورود نداشته باشه! با تشکر
کد ویرایش شد، منتها تکیه بر واسط کاربری با درج صرفا قسمتی از یک عبارت خیلی قابل اعتماد نیست و احتمال اشتراک اطلاعات سیستم ها وجود دارد یا کاربر اگر کمی آشنایی داشته باشد می تواند اطلاعات User-agent را به شکل غیرواقعی تغییر دهد، بهترین حالت این است که یک پین کد به کاربران اختصاص دهید و پین کد را در آدرس URL درخواست کنید، مثال:
example.com/?pin=1234
اگر به درستی تنظیم شده بود صفحه ورود نمایش داده شود در غیر اینصورت به فرض پیام خطای HTTP 404 یا 403 تنظیم کنید.
سینا
۰۰:۰۴ ۱۴۰۱/۰۷/۰۲
با تشکر از شما
بله بصورت شی گرا است. شما بصورت عادی بررسی کنید ممنون میشم، اینطوری مثلا:
<?php
$LimitSystemLogin = 'JNY,A736B,JNX,A521B';
$LoginSystemLimit = explode(",",$LimitSystemLogin);
$LoginSystemLimit = array_map('trim',$LoginSystemLimit);
$server = strip_tags($_SERVER['HTTP_USER_AGENT']);
$valid_agent = false;
foreach($LoginSystemLimit as $_LoginSystemLimit) {
if(!empty($LimitSystemLogin) and stripos($server, $_LoginSystemLimit) !== false) {
$valid_agent = true;
break;
}
}

if($valid_agent === false) {
echo 'شما با این دستگاه مجاز به لاگین به پنل کاربری نیستید!';
} else {
echo 'OK!';
}
?>
کد بالا بر اساس نیاز شما ویرایش شد، می توانید از این نمونه ساختار الگوبرداری کنید.
سینا
۰۶:۰۲ ۱۴۰۱/۰۷/۰۱
با سلام و خسته نباشید
من می خواهم واسه سیستم های کاربران کاری کنم که کاربرانی که سیستم اونا تعریف نشده است نتونن وارد پنل کاربری شوند.
مثلا برای یک کاربر سه تا سیستم تعریف کرده ام که بتونه با همین ها وارد پنل کاربری بشه که در هر خط یک سیستم رو تعریف کردم، از روی یوزر ایجنت که اگه تطابق داشتن وارد بشه ولی اگه تطابق نداشت نتونه وارد بشه ولی هرکاری می کنم درست درنمیاد و می دونم اشتباه دارم مثلا اینهارو برای یک کاربر تعریف کردم
JNY
A736B
JNX
A521B
کدهامم اینه:
<?php
$LimitSystemLogin = Option::model()->get('LimitSystemLogin',$this->userId);
$LoginSystemLimit = explode("\n",$LimitSystemLogin);
$LoginSystemLimit = array_map('trim',$LoginSystemLimit);
$server = strip_tags($_SERVER['HTTP_USER_AGENT']);
foreach($LoginSystemLimit as $_LoginSystemLimit)
{
if( ! empty($LimitSystemLogin) and stripos($server, $_LoginSystemLimit)===false)
throw new CHttpException(404,'شما با این دستگاه مجاز به لاگین به پنل کاربری نیستید!');
}
?>
ممنون میشم راهنمایی کنید و کمکم کنید.
با تشکر از شما و آرزوی موفقیت برای شما و عزیزانتون
نمونه کدهایی که درج کرده اید به صورت شی گرا و وابسته به کلاس های دیگری هستند، به همین دلیل امکان تست و خطایابی مستقل برنامه وجود ندارد با این حال می توانید با دستوراتی مانند var_dump متغیرهای اصلی را حین اجرا بررسی کنید، به فرض:
var_dump($LoginSystemLimit);
باید ببینید خروجی کدام قسمت آنطور که باید باشد نیست.
۲۰:۴۲ ۱۴۰۱/۰۴/۱۸
سلام دوباره.
فایل ها در هاست دانلودی قرار دارند. یعنی من دستور را در هاست دانلودی قرار بدم؟
در هاست دانلودی فایل htaccess وجود ندارد! آیا ایجاد بکنم؟
این دستورات را در بین خطوط فایل htaccess قرار بدم یا جایگاه خاصی دارد؟
با تشکر
بله باید در هاستی قرار بگیرد که فایل ها قرار دارند منتها سرور باید از دستورات htaccess پشتیبانی کند (در این مورد از پشتیبانی سرورتان می توانید سوال کنید)، بهتر است یک فایل htaccess آماده را از سرور وردپرسی کپی و به سرور دانلود منتقل کنید، دستورات را در انتهای فایل درج کنید (البته خیلی اهمیتی ندارد کجا باشند).
نکته: اگر هاست دانلود از فایل htaccess پشتیبانی نکند راه کار ساده ای وجود ندارد و احتمالا باید اسکریپت اختصاصی نوشته شود.
۱۹:۱۳ ۱۴۰۱/۰۴/۱۸
سلام وقت بخیر.
من سایتم وردپرس و در سی پنل هست. میخواستم که فایل هایی که لینک قرار میدم برای کاربران ( با فرمت های mp4 و m4v ) فقط و فقط دانلود بشن و در مرورگر باز نشن. روش های موجود در اینترنت را انجام دادم و تگ های مختلفی به htaccess سایت اضافه کردم اما جوابی نگرفتم.
AddType application/octet-stream .mov
AddType application/octet-stream .m4v
AddType application/octet-stream .mp4
نمونه فایل اضافه کرده. ولی جواب نداد. نمی دونم به درستی در htacces وارد نکردم یا اینکه راه حل دیگه ای داره. ممنون میشم راهنمایی کنید
لطفا فایل htaccess را به همراه نمونه دستورات زیر در ریشه سایت یا در دایرکتوری قرار دهید که فایل های دانلودی در آن وجود دارند:
<FilesMatch "\.(mov|mp4|m4v)$">
ForceType application/octet-stream
Header set Content-Disposition attachment
</FilesMatch>
تست کنید اگر خطایی بود بررسی کنیم.
حامد
۰۲:۲۸ ۱۴۰۱/۰۳/۲۷
سلام و وقت بخیر
من میخوام دسترسی کاربر وقتی مستقیم یا با ورود از جاهای مختلف به یک سایت دوم رو مسدود کنم و پیامی بیاد که بگه شما غیرمجاز وارد شدید برای ورود صحیح به سایت اول مراجعه کنید و با کلیک روی گزینه سایت دوم به این بخش دسترسی خواهید داشت.
یعنی تنها کاربر با ورود به سایت اول و کلیک روی لینک به سایت دوم دسترسی داشته باشه و در غیر این صورت خطا بده و پیامی ظاهر بشه.
میشه چنین کدی نوشت تو php ؟
ممنون میشم اگه راهنماییم کنید.
امکان نوشتن کد بررسی سایت اول در سایت دوم وجود دارد منتها باید ابتدا در سایت اول یک کد یکتای اتفاقی برای هر نشست به فرض بر مبنای IP ایجاد و در دیتابیس ذخیره سازی و کد را به عنوان پارامتر در آدرس URL قرار دهید، به فرض:
http://example.com/?token=1234
در ادامه در سایت دوم با هر بار فراخوانی صفحه ابتدا در پس زمینه IP کاربر را به سایت اول بدهید و کد یکتا را دریافت کنید (برای نقل و انتقال می توانید از تابع cURL یا file_get_contents استفاده کنید)، اگر کد یکتا وجود داشت و با مقادیر تنظیم شده در آدرس URL که از طریق متد GET قابل دریافت است یکی بود یعنی کاربر مجاز است در غیر اینصورت یعنی اگر کدها تطبیق نکردند یا پارامتری در آدرس URL نبود دسترسی غیرمجاز است، برای سختگیری بیشتر می شود کد را یکبار مصرف کرد و با هر درخواست سایت دوم از سایت اول کد منقضی شود.
عظیمی
۱۳:۲۳ ۱۴۰۱/۰۳/۱۸
با سلام
کاربرد اسکریپت
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
در فایل htaccess چیست؟
سربرگ HTTP_AUTHORIZATION یکی از سربرگ های HTTP است که می تواند بین واسط کاربری (مرورگر) و سرور رد و بدل شود، این سربرگ در خصوص صفحات یا منابعی در سرور است که جهت دسترسی به آنها نیاز به نام کاربری و کلمه عبور معتبر داریم و به عبارتی یک شیوه محافظت از منابع سرور است، اما در مورد کاربرد دستور htaccess بالا تا آنجا که اطلاع داریم در سرورهایی که از PHP به عنوان ماژول مستقل (به فرض php5_module) استفاده می کنند این سربرگ مستقیما توسط PHP و در متغیر سراسری SERVER دریافت می شود:
$_SERVER['HTTP_AUTHORIZATION'];
اما در سرورهایی که از PHP به صورت CGI/FastCGI استفاده می کنند نیاز است که ابتدا سربرگ در حالت fcgi_module دریافت و سپس به مفسر PHP ارسال شود که دستور htaccess بالا این کار را انجام می دهد (به عبارتی دستور بالا جهت اطمینان و سازگاری تمام سرورها با نحوه دریافت پارامتر HTTP_AUTHORIZATION در PHP کاربرد دارد).
شریفی
۱۶:۰۷ ۱۴۰۰/۰۹/۰۹
خیلی ممنونم. واقعا عالی بود.
شریفی
۱۹:۴۹ ۱۴۰۰/۰۹/۰۷
بسیار عالی. کارم راه افتاد.
متشکرم.
خواهش، برای سایر فرمت ها باید از روش زیر استفاده کنید:
$file_type = mime_content_type('file.zip');
header("Content-Type: $file_type");
شریفی
۱۸:۲۸ ۱۴۰۰/۰۹/۰۷
سلام. وقت بخیر.
من از دستور زیر برای ارسال فایل به مرورگر کاربر استفاده می کنم. حجم فایل کمتر از 30 مگابایته و فرمتش zip هست.
header("Content-Type: application/octet-stream");
header("Content-Transfer-Encoding: Binary");
header("Content-Length: ".filesize(234234));
header("Content-disposition: attachment; filename=\"Ali.zip\"");
readfile(Ali.zip);
exit();
توی مرورگر به صورت کامل درست عمل می کنه و فایل با فرمت زیپ دانلود میشه. اما توی اندروید فایل با فرمت bin دانلود میشه و نه زیپ. خواستم ببینم مشکل کجاست؟
آیا هدری از قلم افتاده؟ احتمالا به این
header("Content-Transfer-Encoding: Binary");
مربوط میشه اما نمیدونم چطور حلش کنم.
به جای
header("Content-Type: application/octet-stream");
کد زیر را جایگزین کنید ببینید تغییری ایجاد می شود یا خیر؟:
header("Content-Type: application/zip");
البته این دستور فقط برای دانلود فایل ZIP مناسب است.
شریفی
۱۴:۰۶ ۱۴۰۰/۰۷/۲۴
ممنونم. لطف کردین. یعنی در کل روش سوم رو به روش دوم ترجیح می دین؟ حجم فایل ها حداکثر ۲۵ مگابایته و خیلی به امکان resume نیاز نیست. بیشتر امنیت و عدم دسترسی کاربران به فایل مهمه.
من خودم فکر میکنم روش دوم از سوم بهتر باشه، البته کار نکردم و نمی‌دونم چقدر میشه روی ریدفایل در اتصال ftp حساب باز کرد.
در روش دوم پهنای باند هم از هاست دانلود مصرف میشه و هم از هاست اصلی. درسته؟ یا یه جورایی بخش دانلود پاس داده میشه به هاست دانلود؟ یعنی مدیریت اتصال با هاست اصلی باشه و فایل از طریق ftp از هاست دانلود به مرورگر کاربر پاس داده بشه.
در صورتی که امکان اجرای دستورات PHP در هاست دانلود فراهم باشد قطعا روش سوم بهتر است، با توجه به توضیحات تابع ftp_get در آدرس زیر:
https://www.php.net/manual/en/function.ftp-get.php
در روش دوم سرور اصلی فایل را از سرور دانلود دریافت و همزمان به سمت واسط کاربری ارسال می کند، سرور اصلی دو مرحله و سرور دانلود یک مرحله پهنای باند را مصرف می کنند.
شریفی
۱۰:۱۶ ۱۴۰۰/۰۷/۲۴
سلام. ممنونم برای پاسخ خوبتون.
حالا چند تا نکته. قطعا یه راه ایمن و خوب برای این تیپ سایت ها وجود داره. من الان یه هاست اشتراکی دارم و حجم فایل های دانلودی زیادی دارم که کاربر بعد از پرداخت باید بهش دسترسی داشته باشه. خیلی از سایت ها دارن این کارو انجام میدن. من چند تا راه حل به ذهنم رسیده :
1- بعد از پرداخت پول ، فایل با ftp از هاست دانلود در پوشه موقت در هاست اصلی کپی بشه و بعدش با دستور هدر در اختیار کاربر قرار بگیره.
2- بعد از پرداخت پول ، فایل با ftp از هاست دانلود واکشی بشه و با دستور ریدفایل در هدر در اختیار کاربر قرار بگیره. مثل کد زیر:
header('Content-Disposition: attachment; filename="'.$_GET['filename'].'"');
$tempFile = 'temp'.rand();
ftp_get($ftp, $tempFile, $_GET['filename'], FTP_BINARY);

readfile($tempFile);
3- بعد از پرداخت پول ، فایل در هاست دانلود به یه پوشه موقت دیگه در هاست دانلود کپی بشه و لینک جدید در اختیار کاربر قرار بگیره و بعد از یه مدت خاص فایل از پوشه موقت حذف بشه.
نقص روش 1 : هم فضای زیادی از هاست اصلی میگیره و هم ممکنه از منابع زیاد استفاده کنه و سرعت دانلود هم کمه.
نقص روش 2 : دقیقا ایراد این مورد رو نمی دونم چون فایل با ftp به صورت دستور هدر ارسال میشه. به نظر شما آیا این روش مناسبه؟ و از منابع هاست اصلی کمتر استفاده میشه؟؟؟
نقص روش 3 : ممکنه فضای زیادی توی پوشه موقت در هاست دانلود مصرف بشه و از طرف دیگه احتمال لو رفتن آدرس فایل های دیگه توی پوشه موقت وجود داره.
به نظر شما کدام راه بهتره؟ و آیا راه دیگه ای هم هست که به ذهن من نرسیده؟
از این روش ها اگر مورد سوم عملی باشد به نظر بهینه تر است منتها انجام این حالت نیاز به پشتیبانی از اجرای کدهای PHP در هاست دانلود دارد که معمولا چنین قابلیتی فراهم نیست، در صورت فراهم بودن اجرای PHP برای اسم دایرکتوری می شود کد یکتا در سرور اصلی ایجاد و در آدرس URL به هاست دانلود ارسال و در هاست دانلود با متد GET مقدار را دریافت و به عنوان نام دایرکتوری استفاده کرد (هر فایل در یک دایرکتوری با نام اتفاقی)، برای حالت دوم متاسفانه هنوز فرصت نشده تا اسکریپتی با این هدف بنویسیم و دقیق تست کنیم، به نظر مشکل اصلی در این وضعیت پشتیبانی از امکان ادامه دانلود (Resume) است، نکته دیگر عدم نمایش URL اصلی فایل برای کاربر در برنامه هایی مانند IDM است که باید ببینید در عمل به چه شکلی است، البته چون فرآیند دریافت و ارسال فایل در سرور اصلی انجام می شود احتمالا از این نظر مشکلی وجود نداشته باشد، پایداری این روش برای فایل های خیلی حجیم باید بررسی شود. روش اول هم به نظر جالب نباشد چون ابتدا باید فایل بین دو سرور منتقل (Transfer) و سپس برای کاربر ارسال شود که در این بین یک مرحله اضافه وجود دارد و احتمالا کیفیت کار افت می کند.
شریفی
۱۹:۵۸ ۱۴۰۰/۰۷/۲۳
سلام و عرض احترام
ممنون برای اموزش خوبتون. یه سوال خدمتتون داشتم. من یه سایت دانلود دارم که کاربر بعد از لاگین فلان فایل رو میخره و دانلود می کنه. حالا بعد از انجام مراحل شناسایی کاربر و .... با استفاده از دستور زیر فایل رو در اختیار کاربر قرار میدم.
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"...");
readfile(...);
حالا حجم فایل ها زیاد شده و می خوام هاست دانلود بخرم. توی هاست دانلود هم نباید آدرس مستقیم فایل در اختیار کاربر قرار بگیره و من با htaccess در هاست دانلود دسترسی مستقیم به فرمت ها رو بستم. چطور باید کاری کنم که کد بالا اجرا بشه؟ چون کد بالا توی هاست اشتراکی داره اجرا میشه اما فایل توی هاست دانلود هست؟ من هنوز هاست دانلود نخریدم و دارم راجع بهش تحقیق می کنم. آیا کد بالا همین جوری کار می کنه؟ (بعید می دونم چون دسترسی به فرمت ها و آدرس مستقیم فایل از طریق htaccess در هاست دانلود بسته شده) آیا راهی هست که فقط آی پی هاست اشتراکی به فایل دسترسی داشته باشه و بعد بشه با دستور بالا فایل رو در اختیار کاربر قرار داد؟
خلاصه سوال :
ساز و کار سایتی با موضوع دانلود که خودش و دیتابیسش در هاست معمولی هست ولی فایل ها در هاست اشتراکی هست و این فایل ها بعد از خرید در اختیار کاربر قرار میگیره چیه؟
ممنونم. ببخشید سوالم طولانی شد.
متاسفانه تا این لحظه اسکریپتی برای مدیریت این حالت ننوشته ایم اما در تئوری می شود با کد htaccess زیر دسترسی تمام IP ها به جزء IP سرور اصلی را مسدود کرد:
Order Allow,Deny
Deny From All
Allow from 111.222.333.444
همچنین برای دریافت غیرمستقیم فایل از سرور دانلود به نظر باید با یکی از روش های زیر یک حالت پراکسی (بین مرورگر کاربر، سرور اصلی و سرور دانلود) ایجاد کنیم به فرض یا باید از FTP استفاده کنیم، به این صورت که از سرور اصلی به هاست دانلود درخواست دهیم و با تنظیم نام کاربری و کلمه عبور حساب FTP، فایل را از هاست دانلود دریافت و به مرورگر کاربر ارسال کنیم (ظاهرا از این روش در برخی افزونه های وردپرس بیشتر برای آپلود فایل استفاده شده است)، روش دیگر استفاده از توابعی مانند fopen است که می شود فایل را از راه دور (Remote) دریافت و به مرورگر ارسال کرد، البته برای ایجاد قابلیت Resume باید اسکریپت پیچیده تری نوشت که از حالت Chunk و Range استفاده کند، همچنین استفاده از پروتکل SSH و توابع مربوطه در PHP می تواند گزینه دیگری باشد.
more لطفا پیش از ارسال دیدگاه نکات زیر را مد نظر داشته باشید:
- به سوالات کلی، زمانبر، مبهم و مشکلاتی که تلاشی برای رفع آنها نکرده باشید پاسخ مختصر داده شده یا به بخش برنامه نویسی اختصاصی ارجاع داده می شوند.
- کدها و اسکریپت های طولانی را ترجیحا در یک صفحه وب آنلاین یا به صورت حساب موقت و آزمایشی قرار دهید تا امکان بررسی دقیق مشکل و خطایابی میسر باشد.
- تمام دیدگاه های ارسالی خوانده شده و برای هر کاربر مدت زمان لازم جهت پاسخگویی در نظر گرفته می شود، لطفا از طرح سوالات متعدد در بازه زمانی کوتاه خودداری کنید.



 refresh
10 × 10
7 × 3
20 × 20
=