• 0 رای - 0 میانگین
  • 1
  • 2
  • 3
  • 4
  • 5
Download logger
#1
اینو واسه لاگ کردن دانلودهایی که انجام میشه نوشتم.

این میره توی htaccess
کد:
RewriteCond "%{REQUEST_URI}" "/files/" [NC]
RewriteRule "^files/(.*)" "download.php?file=$1" [L]
اینم کد download.php
کد پی‌اچ‌پی:
<?php

$t1
=time();

$path_parts=pathinfo($_GET['file']);
$file_name=$path_parts['basename'];

$file='../files/'.$file_name;
$size=filesize($file);

header('Content-Type: application/octet-stream');
header("Content-Disposition: attachment; filename=\"$file_name\"");
header("Pragma: public");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Length: $size");

ob_flush();
flush();

set_time_limit(60*30);
ignore_user_abort(true);

$min_duration=5;

$chunk_size=1024;

$fp=fopen($file'rb');

$output_bytes=0;

while(!
feof($fp)) {
    
$out=fread($fp$chunk_size);
    if(
feof($fp)) {
        
$duration=time()-$t1;
        
$delta=$min_duration-$duration;
        if(
$delta<0$delta=0;
        
$tmp=substr($out0strlen($out)-$delta);
        echo 
$tmp;
        
ob_flush();
        
flush();
        if(
connection_aborted()) break;
        
$output_bytes+=strlen($tmp);
        
$duration=time()-$t1;
        for(
$i=0$i<$delta$i++) {
            
sleep(1);
            echo 
substr($out$i-$delta1);
            
ob_flush();
            
flush();
            if(
connection_aborted()) break;
            
$output_bytes++;
        }
    }
    else {
        echo 
$out;
        
ob_flush();
        
flush();
        if(
connection_aborted()) break;
        
$output_bytes+=strlen($out);
    }
}
fclose($fp);

$total_duration=time()-$t1;
if(!isset(
$duration)) $duration=$total_duration;

$speed=($output_bytes/$duration)*8;
if(
$speed>1000*1000) {
    
$speed/=1000*1000;
    
$speed_unit='Mbps';
}
else if(
$speed>1000) {
    
$speed/=1000;
    
$speed_unit='Kbps';
}
$speed=number_format($speed2);

$size2=$size;
if(
$size2>1000*1000) {
    
$size2/=1000*1000;
    
$size_unit='MB';
}
else if(
$size2>1000) {
    
$size2/=1000;
    
$size_unit='KB';
}
$size2=number_format($size22);

$report="time: ".time();
$report="\nfile: $file_name";
$report.="\nsize: $size2 $size_unit";
$report.="\nduration: $duration";
$report.="\ntotal duration: $total_duration";
$report.="\nspeed: $speed $speed_unit";
$report.="\nip: {$_SERVER['REMOTE_ADDR']}";
$report.="\nuser agent: {$_SERVER['HTTP_USER_AGENT']}";
if(
connection_aborted()) $report.="\naborted at ".round(($output_bytes/$size)*100)."% ($output_bytes/$size)";
$report.="\n\n";

$fp=fopen('download_log.txt''a');
flock($fpLOCK_EX);
fwrite($fp$report);
fclose($fp);

?>
فعلا در مرحلهء تست هست.
خوبه بنظرتون؟
یخورده عجیب غریب و پیچیده نیست؟ Big Grin
خب بخاطر اینه که سعی کردم به کاربر فرصت بدم تا دانلود رو کنسل کنه! مثلا یه فایل باشه کم حجم باشه سه سوت دانلود میشه کاربر فرصت کنسل کردن نداره، چون حتی موقعی که کاربر هنوز به مرورگر فرمان سیو کردن یا کنسل کردن دانلود فایل رو نداده، مرورگر خودش در حال دریافت فایل از سمت سرور هست. بنابراین من اگر زمان دانلود کمتر از یک مقداری باشه (min_duration) میام و چند بایت ته فایل رو سمت سرور نگه میدارم و هر ثانیه یک بایتش رو میفرستم واسه مرورگر (جیره بندیه Big Grin). اینطور کاربر فرصت بیشتری داره که کنسل کنه و میشه سمت سرور فهمید و لاگ کرد که واقعا قصد دانلود داشته یا نه. چون من خودم که خیلی وقتا دانلود رو کنسل میکنم یا از اول هم قصدم دانلود نبوده فقط کلیک کردم مثلا ببینم مشخصاتش چیه داستانش چیه حجمش چقدره و این حرفا.
البته اینو روی لوکال تست کردم، الان فرستادم روی هاست مثل اینکه داستانش یخورده فرق میکنه!
  پاسخ
تشکر شده توسط :
#2
آدم توی بعضی چیزا که میره تازه میفهمه قضیه از چیزی که فکر میکرده پیچیده تر و دشوارتره!
بعضی چیزا تستش هم سخته، منابعی هم تقریبا نداره که روشن کرده باشه همه جزییات و نکات مهم رو گفته باشه.
مثلا من الان یه فایل رو از هاستم دانلود میکنم نصفه دانلود میکنم وسطش کنسل میکنم ولی در لاگ چیزی ثبت نمیشه. وقتی اون فایل رو یک بار کامل دانلود کردم ثبت شد، بعدش که دوباره نصفه دانلود کردم اونم ثبت شد!
فکر کردم شاید این بخاطر کش شدن فایل در کش سرورهای مسیر بوده باشه، به انتهای آدرس فایل دیگری یک رشته اضافه کردم (بعد از ?) که از کش جلوگیری کنم، این بار دانلود ناقص ثبت شد.
ولی علتش هنوزم مبهمه! اگر کش شده بود چطور دانلود کامل برای اولین بار هم که کردم ثبت شد؟! بعدش چرا وقتی دانلود ناقص کردم از یک نسخهء کش شده استفاده نشد؟

خلاصه سوالات بی جواب.
اینا مرد میدون میخواد! چون کارهای حرفه ایه و نیاز به سواد و توانایی بالا داره، کارهای کلیشه ای نیست، چیزهایی نیست که توضیح و کمک واسش همه جا ریخته باشه.
البته من زیاد وقت و حوصله ندارم واسه این کار. شاید اصلا کلا کنسلش کنم! یکی نیست بگه آخه آمار دانلود رو میخوای چکار کنی حالا! نمیدونم، شایدم نیاز نباشه، درواقع دنبال یه پروژهء کوچک جدید بودم که جذاب و آموزنده باشه و دانش و مهارت منو تر و تازه نگه داره. الان دیگه من باید از مغزم مدام کار بکشم تقویتش کنه آپدیتش کنم از اونور ازش بهره وری بشه خب Wink
  پاسخ
تشکر شده توسط : Alaa ali_asadi
#3
اینجا نسخهء پیشرفته ترشه: https://github.com/ferchang/download-logger
یکی دو باگ هم داشت که درست کردم. البته هنوز در مرحلهء آزمایشیه.
  پاسخ
تشکر شده توسط :
#4
پیاده سازی دانلود فایل با php کار احمقانه ای هست. دلایل زیادی وجود داره . مثل اینکه read از هارد توی وب سرور قطعا بهینه تر هست و از طرف دیگه مصرف رم و ریسورس توی php خیلی بیشتر هست. از طرف دیگه تو باید هدرها رو هم چک کنی. مثلا برای قابلیت رزیوم و خیلی چیزهای دیگه که توی وب سرور پیشبینی شده. به نظرم استفاده از خود وب سرور بهتره.
راستی می تونی با خیال راحت از GO هم استفاده کنی Tongue
  پاسخ
تشکر شده توسط :
#5
آره میدونم، ولی منکه دانلود سنتر ندارم! اینا همش یه مشت فایل شخصی مربوط به مقاله های وبلاگمه که اکثرشون هم حجم زیادی ندارن.
بنابراین بهینه سازی در اینجا برای من اصلا مهم نیست، و در عمل هم خیلی بعیده مشکلی از نظر پرفورمنس بوجود بیاد، چون گهگاهی فقط یکی دوتا فایل میخواد دانلود بشه که اونم اکثرا کم حجم هستن. مثلا این چند وقته گذاشتم این اسکریپت تست بشه تعداد دانلود کمی صورت گرفت که بیشترش هم روبات های مختلف بودن و فایلهای دانلود شده هم خیلی کم حجم بودن.
البته همونطور که از اول گفتم این یک تمرین برنامه نویسی هم بود گفتم یجوری خودمو مشغول کنم چون از خیلی وقت پیش این ایده توی ذهنم بود گفتم عملی کنم ببینم چی از آب درمیاد و در آینده هم شاید به دردم خورد.
اول میخواستم دانلود رو توی PHP فقط لاگ کنم و بعدش ریدایرکت کنم برای دانلود مستقیم که دیگه مثل حالت معمول انجام بشه، ولی خب اینطوری امکان چک کردن و لاگ کردن یکسری پارامترها از بین میرفت (مثلا اینکه دانلود کامل نشده abort بشه یا سرعت دانلود). یعنی بحث اطلاعاتی هم بود که میخواستم دانش و بینشم در این مورد هم بالا بره ببینم دقیقا توی وب و بحث دانلود HTTP چه اتفاقاتی داره میفته.

قابلیت resume هم میتونستم بذارم ولی دیدم اکثر فایلها حجمی ندارن نیاز نیست و برنامه رو بیخود پیچیده نکنم بهتره.
  پاسخ
تشکر شده توسط :


پرش به انجمن:


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