i
در حال برنامه نویسی و آماده سازی نسخه جدید «وبگو» هستیم، در این نسخه قابلیت ها و ظاهر سایت به کلی متفاوت و کاملتر خواهد بود، این فرآیند زمانبر و از مدتی پیش شروع شده و همچنان ادامه دارد، روند پیشرفت پروژه در این قسمت به صورت درصدی مشخص است و به تناوب به روزرسانی می شود.
parsgreen.com
article

محدود کردن لینک دانلود مستقیم فایل ها با 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>
<!-- http://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
sectionدسته بندی: آموزش کاربردی » PHP
related مطالب بیشتر:
» ارسال پارامتر به URL و دریافت مقادیر با PHP
» ساخت منوی هوشمند با php و css!
» نحوه نمایش متن و تصاویر اتفاقی در php و mysql
» آموزش ساخت نقشه سایت (Sitemap) با php و xml
» نمایش قسمتی از متن و پاراگراف با php
commentنظرات (۸۸ یادداشت برای این مطلب ارسال شده است)
نویسنده: زهرا
زمان: ۱۰:۲۲:۳۳ - تاریخ: ۱۳۹۵/۰۲/۲۹
سلام استاد ممنون از سایت خوبتون اگه میشه اموزش سبد خرید و هم بذارید ممنون میشم
پاسخ: 
متاسفانه در کوتاه مدت امکانپذیر نیست!
نویسنده: مهدی حسامی
زمان: ۱۴:۲۶:۳۴ - تاریخ: ۱۳۹۵/۰۳/۲۷
سلام عرض می کنم خدمت مدیریت سایت و کاربران
جهت هدایت کاربر در زمان دانلود فایل دستورات درج شده در سایت ممکنه برای نسخه های جدیدتر آپاچی کار نکنه که میتونید از کد پائین استفاده کنید
RewriteEngine On
# you can add whatever extensions you want routed to your php script
RewriteCond %{REQUEST_URI} \.(doc|zip|pdf)$ [NC]
RewriteRule ^(.*)$ /download-file.php?filename=$1 [L]
پاسخ: 
تشکر فراوان از بابت به اشتراک گذاری.
نویسنده: پارسا
زمان: ۱۹:۴۵:۴۰ - تاریخ: ۱۳۹۵/۰۳/۳۰
با سلام
من سیستمی برای دانلود فایل برنامه نویسی کردم و همه کارها خوب پیش میرفت تا اینکه فضای هاستم پر شد و مجبور شدم یه سرور برای فایل هام خریداری کنم و حالا فایلهام روی یه سرور با یه آی پی هست و اسکریپتم روی یه هاست!
من قبلا کدم رو کامل و بدون مشکل نوشته بودم و دانلودم بدون مشکل انجام میشد از این سیستم استفاده کرده بودم :
http://osxdaily.com/2014/02/13/download-with-curl/
حالا که سرورم عوض شده نیاز دارم که دانلود من از یک آدرس انجام بشه ولی با این کد فقط امکان دانلود از درون سرور هست
شما چه پیشنهادی دارید؟
و یه سوال دیگه مثلا من اگه این کد رو درون سرورم قرار بدم آیا میشه این که کاربر تو سایت اصلی لاگین هست یا نه رو سیزنش رو برسی کرد ؟
چگونه ؟
یعنی با یک فایل PHP سیزن لاگین بودن در یه سایت رو از یک سرور دیگه بررسی کنیم
پاسخ: 
کار با دو سرور امکانپذیر است منتها نه به اندازه کیفیت و سهولت حالت عادی، به طور مثال برای بررسی وضعیت لاگین بودن می توان یک درخواست با curl به هاست اسکریپت ارسال کرد و بر اساس پارامترهای ارسالی (نام کاربری، در صورت نیاز کلمه عبور رمزی شده) وضعیت لاگین بودن کاربر را در دیتابیس بررسی و نتیجه را برگداند، در حالت حرفه ای به تجهیزات سخت افزاری نیاز است تا بتوانید مانند سایت های بزرگ وب، خدمات آپلود و میزبانی فایل ارائه کنید در غیر این صورت بهتر است اسکریپت و فایل در یک سرور میزبانی شوند، این شیوه برای سایت های کوچک و متوسط راحتتر و بهتر است.
نویسنده: علی
زمان: ۲۲:۳۲:۱۰ - تاریخ: ۱۳۹۵/۰۴/۰۱
سلام. خداقوت. به نظر شما کسی که دوره آموزشی مقدماتی را گذرانده باشد مثلا کار با متغیرها، آرایه ها، شی گرایی و... باید برای پیش رفتن و حرفه ای شدن در php چه کند؟
پاسخ: 
در صورتی که احساس می کنید آموزش های مقدماتی را به اندازه کافی فرا گرفته اید، بهترین راه برای ارتقاء دانش و تجربه برنامه نویسی پروژه واقعی (از پروژه های سبک تا سنگین) است، معمولا در حین ساخت پروژه نیاز به مطالعه و تمرین بیشتر احساس می شود.
نویسنده: پرهام
زمان: ۰۳:۱۹:۱۳ - تاریخ: ۱۳۹۵/۰۴/۰۴
باسلام
ممکنه راهنمایی بفرمایید چطور میشه تشخیص داد یه کاربر با نام کاربری و پسورد مخصوص به خودش از چند تا سیستم داره به سایت ما وصل میشه برای دانلود؟
این نکته رو هم در نظر بگیرید که کاربر از طریق مرورگر به سایت وصل نمیشه (پس احتمالا بحث کوکی و سشن غیر کاربردیه) بلکه از طریق اپلیکیشن تحت ویندوز اینکارو داره انجام میده که ما هیچ دسترسی به اون اپلیکیشن نداریم یعنی نام کاربری و پسورد رو توی اون اپلیکیشن وارد میکنه. (مثل یه دانلود منیجر یا آنتی ویروس)
پاسخ: 
شاید تنها راه حل پیش رو استفاده از اطلاعات واسط کاربری یا به اصطلاح User Agent کاربر باشد، با توجه به زبان برنامه نویسی که از آن استفاده می کنید راه حل دریافت این اطلاعات متفاوت خواهد بود، به طور مثال در PHP دستور زیر کاربرد دارد:
$useragent = $_SERVER ['HTTP_USER_AGENT'];
نکته: با توجه به اینکه این اطلاعات از سمت کاربر فرستاده می شوند، لذا ممکن است غیر واقعی نیز باشند (به فرض در مورد دستکاری توسط کاربران حرفه ای یا ربات ها).
نویسنده: پرهام
زمان: ۲۲:۴۵:۳۷ - تاریخ: ۱۳۹۵/۰۴/۰۶
باسلام و تشکر بابت پاسخگویی به سوالات
چطور میشه پسوندهای دیگر فایل که شناخته شده نیستند رو با این روش به شکل غیرمستقیم دانلود کرد
مثلا پسوند prd
من توی فایل htaccess این پسوند رو اضافه کردم
توی قسمت download.php هم هدر زیر رو اضافه کردم
header('Content-Type: application/octet-stream');
ولی موقع دانلود خطای 404 میده
Object not found!
ولی پسوندهای دیگه رو مشکل نداره
چطوری میشه این پسوندهای ناشناخته روبهش اضافه کرد؟
پاسخ: 
اگر مراحل را درست انجام داده باشید نباید مشکلی وجود داشته باشد، در هر صورت پیدا کردن علت و رفع مشکل نیاز به بررسی و تست آنلاین است!
نویسنده: پرهام
زمان: ۰۳:۴۹:۵۷ - تاریخ: ۱۳۹۵/۰۴/۰۷
باعرض سلام و تشکر
پیرو سوال قبلی در صورتیکه کاربر از یک برنامه تحت ویندوز به سایت ما وصل بشه و یوزرنیم و پسورد رو در اون برنامه وارد کرده باشه، ما برای اعتبار سنجی این کاربر چطور میتونیم عمل کنیم؟ یعنی چطور میشه username و password ارسال شده از طریق اون برنامه رو چک کنیم در حالیکه الان لینک غیرمستقیم شده از طریق htaccess و در فایل download.php چطور باید نام کاربری و پسورد ارسال شده از طریق برنامه رو برای اعتبارسنجی در متغیرهای خودمون قرار بدیم؟
پاسخ: 
هر درخواستی به سرور از طریق هر واسط کاربری که ارسال شود می تواند توسط کدهای PHP و از طریق متد POST یا GET دریافت و بررسی شود، لذا اهمیت خاصی ندارد که کاربر از چه برنامه ای جهت ارسال درخواست به سرور استفاده می کند، می توانید در همان فایل دانلود ابتدا اطلاعات ارسالی از طریق متد POST را بررسی و سپس فایل درخواستی را ارسال یا در صورت مجاز نبودن کاربر از این کار خودداری کنید.
نویسنده: احمد
زمان: ۱۵:۱۸:۲۴ - تاریخ: ۱۳۹۵/۰۴/۲۹
سلام
یک سوال داشتم... قبل از ob_clean نباید ob_start قرار می دادید.
پاسخ: 
بله، سپاس فراوان از یادآوری، تابع اضافه شد!
نکته: استفاده از این توابع برای کارکرد صحیح کد ضرورتی ندارد و صرفا برای جلوگیری از ارسال خروجی های ناخواسته قبل از ارسال فایل به مرورگر است!
http://php.net/manual/en/function.ob-clean.php
نویسنده: رکسانا
زمان: ۱۲:۰۵:۴۵ - تاریخ: ۱۳۹۵/۰۵/۰۵
مررررررررررررررررررررررررررررررسی بابت مطالب مفیدتون
نویسنده: متین
زمان: ۱۰:۳۶:۱۴ - تاریخ: ۱۳۹۵/۰۵/۲۶
سلام ممنون خیلی کامل بود.
نویسنده: iman
زمان: ۲۲:۰۷:۴۶ - تاریخ: ۱۳۹۵/۰۶/۳۰
سلام و خسته نباشید
ممنون بخاطر آموزش
من میخوام مثلا بعد خرید یه لینک به کاربر داده بشه که بصورت یکتا باشه و مثلا تا یک ماه زمان داشته باشه و چون فایل حجیم هست مثلا یک گیگ میخوام کاربر بتونه تو بازه های چند روزه دانلود رو متوقف و ادامه بده...
تو این موارد تو خرید و لینک زمان دار و... مشکل ندارم
مشکلم اینه که با این روش شما اگر کاربر دانلود رو متوقف کنه و مثلا فردا بخواد ادامه دانلود رو انجام بده باز میاد از اول دانلود میکنه idm که این کار برا فایلهای حجیم اشتباهه.
ممنون میشم اگر راه حلی دارید یه راهنمایی کوچیک کنید.
مرسی
پاسخ: 
این آموزش صرفا برای آشنایی اولیه کاربران با اصول کار تهیه شده، برای قابلیت های بیشتر مسلما باید پیچیدگی های بیشتری را به برنامه خود اضافه کنید، روش هایی برای مدیریت ادامه دانلود فایل با PHP وجود دارد، لطفا به لینک زیر مراجعه کنید:
http://stackoverflow.com/questions/157318/resumable-downloads-when-using-php-to-send-the-file
نویسنده: حمیدرضا
زمان: ۰۳:۵۸:۴۷ - تاریخ: ۱۳۹۵/۰۹/۲۷
سلام من این کد رو تست کردم ولی بجای اینکه فایل رو بفرسته برای دانلود روی سرور بازش میکنه مثلا حالتی ک یک فایل موزیک رو با notepad‌ باز میکنیم خرچنگ قورباقه تحویل میده !!! چکارش باید بکنم ؟
ممنون میشم راهنمایی کنید
پاسخ: 
بدون تست و اینکه چه فرمتی را با چه Content Type ای ارسال می کنید نمی توان جواب خاصی ارائه کرد، می توانید از application/octet-stream برای فایل هایی که نمی خواهید در مرورگر اجرا شوند استفاده کنید، همچنین می توانید فایل های خود را به صورت zip شده برای دانلود قرار دهید چون فایل هایی مانند mp3 و... برای دانلود مستقیم نیاز به تنظیمات بیشتری دارند و ممکن است به صورت پیش فرض در مرورگر اجرا شوند! به هر صورت دسترسی به کدها و تست آنلاین برای پی بردن به علت مشکل و رفع آن مورد نیاز است!
نویسنده: الهام
زمان: ۱۵:۳۹:۰۲ - تاریخ: ۱۳۹۵/۱۱/۰۶
مرسی بابت سایت عالی تون
paged صفحه 6 از 6




more لطفا دقت کنید که یادداشت های زیر منتشر نشده و حذف خواهند شد:
- یادداشت های خارج از موضوع این مطلب.
- سوالات کلی، غیر ضروری و مشکلاتی که هیچ تلاشی برای رفع آن نکرده باشید.
- نظرات حاوی کدها و اسکریپت های خیلی طولانی (به طور مثال کد کامل قالب وبلاگ).

5 × 6
 refresh
آگهی
seonab.com
طراحی نرم افزار اندروید
رنگین کمان عکس
Ranginkamaan.com

آرشیو عکس های باکیفیت با موضوعات متنوع...
پرشین آی تی
Persianit.net

آموزش و دانلود پروژه های برنامه نویسی سی شارپ (#C)