<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>یادداشتهای بیت نیمسوز &#187; وب سرور</title>
	<atom:link href="http://cyberrabbits.net/tag/webserver-fa/feed/" rel="self" type="application/rss+xml" />
	<link>http://cyberrabbits.net</link>
	<description>یک وبلاگ دیگر از یک برنامه نویس دیگر</description>
	<lastBuildDate>Wed, 25 Jan 2012 08:37:11 +0000</lastBuildDate>
	<language>fa</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>دو نکته برای بالا بردن سرعت &#8211; آپاچی</title>
		<link>http://cyberrabbits.net/799/apache-speed-up-tips/</link>
		<comments>http://cyberrabbits.net/799/apache-speed-up-tips/#comments</comments>
		<pubDate>Tue, 18 Jan 2011 19:50:31 +0000</pubDate>
		<dc:creator>فرود</dc:creator>
				<category><![CDATA[آپاچی]]></category>
		<category><![CDATA[فوت کوزه گری]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[gzip]]></category>
		<category><![CDATA[webserver]]></category>
		<category><![CDATA[وب سرور]]></category>

		<guid isPermaLink="false">http://cyberrabbits.net/?p=799</guid>
		<description><![CDATA[از نکاتی که پیشنهاد میشه برای بالا بردن سرعت یه سایت این دو مساله سادست: ۱- اضافه کردن Expire Header به فایلها، و خصوصا یک زمان دور برای فایلهای استاتیک، مثلا عکسها و فایلهای css و جاوااسکریپت. البته بد نیست برای فایلهای php و html هم این زمان رو تعیین کنیم ولی نه چندان دور.&#8230;
پستهای مرتبط :<ol>
<li><a href='http://cyberrabbits.net/43/vhosts/' rel='bookmark' title='هاست مجازی بر روی آپاچی'>هاست مجازی بر روی آپاچی</a> <small>خیلی پیش می آید که ما نیاز به چند آدرس...</small></li>
<li><a href='http://cyberrabbits.net/564/a-small-tip-in-php/' rel='bookmark' title='یه نکته کوچک در PHP'>یه نکته کوچک در PHP</a> <small>همونطور که میدونید توی PHP برای اپراتور OR دو نسخه...</small></li>
<li><a href='http://cyberrabbits.net/585/php-simple-note/' rel='bookmark' title='بازم یک نکته کوچک تو PHP'>بازم یک نکته کوچک تو PHP</a> <small>یکی از مشکلاتی که برنامه نویسهای تازه کار با اون...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>از نکاتی که پیشنهاد میشه برای بالا بردن سرعت یه سایت این دو مساله سادست:<br />
۱-<a href="http://developer.yahoo.com/performance/rules.html#expires"> اضافه کردن Expire Header به فایلها</a>، و خصوصا یک زمان دور برای فایلهای استاتیک، مثلا عکسها و فایلهای css و جاوااسکریپت. البته بد نیست برای فایلهای php و html هم این زمان رو تعیین کنیم ولی نه چندان دور.<br />
۲-<a href="http://developer.yahoo.com/performance/rules.html#gzip"> کمپرس کردن فایلهای متنی با متد gzip </a>و فرستادن اونها به کلاینت به جای ارسال محتوای فشرده نشده.</p>
<p>برای هر دو در خود PHP امکاناتی هست، ولی مشکلاتی هم هست. این امکانات که در PHP هستن، طبیعیه که فقط برای فایلهای PHP کار میکنن نه مثلا فایلهای CSS یا JS که اونها مهمترن برای اینکار. یعنی شما میتونید با دستور header استفاده کنید برای ویرایش http header و از تنظیمات PHP هم gzip رو فعال کنید، ولی این فقط برای فایلهایی که PHP پردازش میکنه اعمال میشن نه همه فایلها.<br />
اینجا آپاچی میتونه خیلی کمک کنه. برای اینکار باید دو ماژول معروف‌آپاچی رو نصب کنید.<br />
<span id="more-799"></span><br />
<a href="http://httpd.apache.org/docs/2.0/mod/mod_headers.html"><strong>mod_headers</strong></a><br />
این ماژول، به شما اجازه میده به راحتی Http Header مربوط به یک فایل رو (و در کل تمام پاسخها رو) ویرایش کنید. اول مطمئن بشید روی سرورتون نصبه. بسته به نسخه مورد استفاده شما، میتونید با دستور :</p>
<pre class="brush: plain; title: ; notranslate">
apache2ctl -l
</pre>
<p>یا دستورات مشابه، لیست ماژولهای نصب شده تو آپاچی رو ببینید و مطمئن بشید که این ماژول وجود داره. (نکته جالب اینه که من همیشه این دستور رو میزنم و این ماژول رو لیست نمیکنه! در صورتیکه نصبش کردم و کار هم میکنه! از آرچ ۶۴ بیتی استفاده میکنم و Zend Server CE )‌</p>
<p>حالا به راحتی میتونید از Header توی فایل htaccess استفاده کنید. یه چیزی مثل این رو میتونید توی فایل htaccess بنویسید : </p>
<pre class="brush: plain; title: ; notranslate">
&lt;IfModule mod_header.c&gt;
	Header unset Pragma
	FileETag None
	Header unset ETag

	# cache images/pdf/css/js for 10 days
	&lt;FilesMatch &quot;\.(ico|pdf|jpg|jpeg|png|gif|js|css)$&quot;&gt;
	  Header set Cache-Control &quot;max-age=864000, public, must-revalidate&quot;
	  Header unset Last-Modified
	&lt;/FilesMatch&gt;

	# cache html/htm/xml/txt diles for 2 days
	&lt;FilesMatch &quot;\.(html|htm|xml|txt|xsl)$&quot;&gt;
	  Header set Cache-Control &quot;max-age=7200, must-revalidate&quot;
	&lt;/FilesMatch&gt;
&lt;/IfModule&gt;
</pre>
<p>البته تو این مثال از FileMatch هم استفاده کردم که توی هسته آپاچی هست به صورت پیشفرض.<br />
تو این مثال ETag رو هم غیر فعال کردم (خطوط ۳ و ۴)که اونم به این دلیله : <a href='http://developer.yahoo.com/performance/rules.html#etags' title='Best Practices for Speeding Up Your Web Site'>Best Practices for Speeding Up Your Web Site</a> (آخر قسمت Configure ETags منظورمه، کامل بخونیدش)<br />
و بعد برای فایلهای عکس، pdf ، CSS و جاوا اسکریپت، زمان انقضای ۱۰ روز رو انتخاب کردم(خطوط ۷ تا ۱۰ ) و بعد برای فایلهای متنی استاتیک (نه php البته) مدت زمان انقضای ۲ روز (خطوط ۱۳ تا ۱۵)<br />
کد بالا رو تو htaccess کپی کنید، کار کرد که چه خوب! اگه کار نکرد یعنی ماژول مورد نظر نصب نیست. برای مطمئن شدن از کار کردنش، از افزونه <a href="http://developer.yahoo.com/yslow/">Y!Slow</a> استفاده کنید، یا دو خط اول و آخر (IfModule) رو حذف کنید و ببینید Internal Server Error میگیرید یا نه، اگه خطا نداد یعنی همه چی درسته.</p>
<p><a href="http://httpd.apache.org/docs/2.0/mod/mod_deflate.html"><strong>mod_deflate</strong></a><br />
این یکی به شما امکان میده که به راحتی قابلیت فشرده سازی رو روی فایلهاتون فعال کنید. توصیه من فشرده کردن همه فایلهای CSS و جاوا اسکریپت و html هستش. اینطوری : </p>
<pre class="brush: plain; title: ; notranslate">
&lt;IfModule mod_deflate.c&gt;
  &lt;FilesMatch &quot;\.(js|css|php|htm|html)$&quot;&gt;
    SetOutputFilter DEFLATE
  &lt;/FilesMatch&gt;
&lt;/IfModule&gt;
</pre>
<p>با این روش در صورتیکه این پسوندهای به خصوص درخواست بشن توسط سرور، سرور اونها رو کمپرس شده پس میفرسته.<br />
البته php هم معمولا خروجیش html میشه بودنش تو این لیست بدک نیست. برای امتحان درست بودن این، مثل همون که بالا گفتم عمل کنید، دو خط اول و آخر رو حذف کنید و ببینید بازم کار میکنه یا خطا میگیرید.<br />
البته، راهنمای خود ماژول هم این فرم استفاده رو پیشنهاد کرده : </p>
<pre class="brush: plain; title: ; notranslate">
AddOutputFilterByType DEFLATE text/html text/plain text/xml
</pre>
<p>که فرق آنچنانی نداره و شاید بعضی ها اینو دوست تر داشته باشن :)<br />
یه نکته هم بد نیست بگم و اونم اینه که توی FilesMatch از عبارات با قاعده استفاده میشه، و مثلا </p>
<pre class="brush: plain; title: ; notranslate">
\.(html|htm|xml|txt|xsl)$
</pre>
<p>یعنی هر فایلی که تو اسمش یه نقطه باشه بعد بلافاصله html یا htm یا xml یا txt یا xsl باشه و بعدش هم بلافاصله اسم فایل تموم بشه (اون علامت $ اینو میگه!)</p>
<p>&#8211; یه مدتیه درگیر یه سری کار و سفارش هستم کمتر وقت میکنم بنویسم&#8230;‌</p>
<div class="plus-one-wrap"><g:plusone href="http://cyberrabbits.net/799/apache-speed-up-tips/"></g:plusone></div><p>پستهای مرتبط :<ol>
<li><a href='http://cyberrabbits.net/43/vhosts/' rel='bookmark' title='هاست مجازی بر روی آپاچی'>هاست مجازی بر روی آپاچی</a> <small>خیلی پیش می آید که ما نیاز به چند آدرس...</small></li>
<li><a href='http://cyberrabbits.net/564/a-small-tip-in-php/' rel='bookmark' title='یه نکته کوچک در PHP'>یه نکته کوچک در PHP</a> <small>همونطور که میدونید توی PHP برای اپراتور OR دو نسخه...</small></li>
<li><a href='http://cyberrabbits.net/585/php-simple-note/' rel='bookmark' title='بازم یک نکته کوچک تو PHP'>بازم یک نکته کوچک تو PHP</a> <small>یکی از مشکلاتی که برنامه نویسهای تازه کار با اون...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://cyberrabbits.net/799/apache-speed-up-tips/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>دانلود فایل با قابلیت Resume در PHP</title>
		<link>http://cyberrabbits.net/264/download-with-resume-support-in-php/</link>
		<comments>http://cyberrabbits.net/264/download-with-resume-support-in-php/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 20:22:56 +0000</pubDate>
		<dc:creator>فرود</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[برنامه نویسی]]></category>
		<category><![CDATA[download manager]]></category>
		<category><![CDATA[webserver]]></category>
		<category><![CDATA[وب سرور]]></category>

		<guid isPermaLink="false">http://cyberrabbits.net/?p=264</guid>
		<description><![CDATA[کد انتهایی یه مشکل کوچک داشت که اصلاح شد :)‌ ایندفعه،‌میخوام یه چیزی بنویسم درباره دانلود (آخرش هم نفهمیدم که این کلمه رو به فارسی چی بگیم!! بارگزاری،‌بارگیری، گرفتن ..)‌ خیلی وقتها میخوایم که یه فایل رو محافظت کنیم که همینجوری دانلود نشه، یعنی حتما اسم کاربری بخواد، یا اینکه مطمئن شیم که فایل حتما&#8230;
پستهای مرتبط :<ol>
<li><a href='http://cyberrabbits.net/403/source-forge-redirector/' rel='bookmark' title='دانلود از SourceForge بدون مشکل'>دانلود از SourceForge بدون مشکل</a> <small>اسکریپت رو اگه نصب کردید دوباره آپدیت کنید، چون sf...</small></li>
<li><a href='http://cyberrabbits.net/471/http-redirect/' rel='bookmark' title='HTTP Redirect'>HTTP Redirect</a> <small>یه چند وقتی هست که مدام درگیر کارهای امنیتی، خصوصا...</small></li>
<li><a href='http://cyberrabbits.net/411/mysql-menu-part-3/' rel='bookmark' title='Mysql Menu قسمت سوم'>Mysql Menu قسمت سوم</a> <small>چند وقت پیش در باره منو و طریقه ایجاد آن...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><ins datetime="2010-04-10T18:03:56+00:00">کد انتهایی یه مشکل کوچک داشت که اصلاح شد :)‌</ins><br />
ایندفعه،‌میخوام یه چیزی بنویسم درباره دانلود (آخرش هم نفهمیدم که این کلمه رو به فارسی چی بگیم!! بارگزاری،‌بارگیری، گرفتن ..)‌ خیلی وقتها میخوایم که یه فایل رو محافظت کنیم که همینجوری دانلود نشه، یعنی حتما اسم کاربری بخواد، یا اینکه مطمئن شیم که فایل حتما از تو صفحه خودمون دانلود میشه که آمار درست باشه.<br />
یه راه ساده وجود داره، که بیشتر از اون استفاده میشه،‌اونهم به سادگی گذاشتن فایل در یک پوشه خارج از دسترسی مستقیم (مثلا خارج از ریشه وب سرور، یا محافظت شده توسط وب سرور،‌مثلا آپاچی با کمک فایل .htaccess ) و بعد به پس دادن فایل از طریق کد به کاربر. مثلا برای PHP میتونید همچین کدی بنویسید : </p>
<pre class="brush: php; title: ; notranslate">
//Before this point you should check everything
//include user authenticate and any thing else
$result=@readfile('/path/to/file');
if ($result===false)
   //Error :(
else {
   // $result contain byte count
}
</pre>
<p>این روش بد نیست، کاربر نمیتونه لینک مستقیم بگیره، که خوب این معمولا برای خیلی ها مهمه، خصوصا با این وضع وبلاگها و سایتهای ایرانی که متخصص کپی/پیست و گرفتن لینک و گذاشتن به اسم خودشون حتی بدون زحمت آپلود مجدد هستن.<br />
اما یه عیب بزرگ داره،‌این دانلود دیگه قابلیت resume نداره. منم که دقیقا میتونم کاربر دیال آپی رو درک کنم،‌مخصوصا اینکه تو ایران بزرگ شدم!! خوب این شد که نشستم و بررسی کردم که چطوری این مشکل رو هم حل کنم. البته این کارو خیلی وقت پیش انجام دادم، و چون امروز خواهر زاده ام گیر داده بود، ‌پیداش کردم  و یادم افتاد که میشه اینجا بنویسمش،‌و خصوصا اینکه این روزا همش تو فکر اینم که چی بنویسم که ارزش نوشتن داشته باشه .<br />
<span id="more-264"></span><br />
اول باید یه توضیح ساده بدم. اونم اینکه اصلا این روش resume چطور کار میکنه. واسه اینکار سرور باید یه اطلاعاتی رو به صورت header بفرسته به کلاینت در ازای درخواست کلاینت. این کار رو به راحتی میشه انجام داد :</p>
<pre class="brush: php; title: ; notranslate">
	header('Accept-Ranges: bytes');
</pre>
<p>این رو وب سرورها برای هر فایلی که قابلیت resume بخواد داشته باشه میفرستن. البته اگه خود سرور این قابلیت رو داشته باشه. خوب ما هم همینکار رو انجام میدیم یعنی این خط رو به جواب کلاینت اضافه میکنیم، اینجوری حتی اگه خود وب سرور هم این قابلیت رو نداشته باشه ما این قابلیت رو اضافه کردیم (یه بار یه وب سرور مینوشتم، با دلفی و ایندی و خودم این قابلیت رو اونجا اضافه کردم، خیلی سخت نبود :)‌ )<br />
حالا کلاینت وقتی میفهمه که وب سرور این قابلیت رو داره ، علاوه بر آدرس فایل یه سری اطلاعات هم میفرسته.ما کاری با کلاینت نداریم،‌چون تو این حالت کلاینت برنامه دانلود هست، که خوب از بحث ما جداست. این اطلاعات رو میتونید (توی PHP ) از آرایه $_SERVER بخونید. این اطلاعات عبارتند از : </p>
<pre class="brush: php; title: ; notranslate">
	$ranges= $_SERVER['HTTP_RANGE'];
	//Now ranges contain some thing like : Range: bytes=0-500
</pre>
<p>البته توی <a href="http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt">Draft</a> مربوط به این قضیه که من خوندم، که Range میتونه چند تایی باشه که من کاری به اون قضیه ندارم و اصولا هم تا به حال ندیدم تو عمل این چند تایی بودن رو. اما این دو عدد که با یه منها از هم جدا میشن،‌ نشونگر بایتهایی هستند که خواسته شده. علامت منها همیشه باید باشه. اما یکی از دو عدد میتونه نباشه (دو عدد همزمان نمیتونن نباشن) اگه عدد اول نباشه، یعنی یه منها باشه بعد عدد دوم، به معنی درخواست n بایت انتهایی فایل هست، که n میشه همون عدد دوم.<br />
اما اگه عدد دوم نباشه، یعنی یه عدد m بعد یه منها،‌به این معنیه که از بایت m شروع کن تا آخر فایل خواسته شده. یادتون هم باشه که بایتها از صفر شروع میشن، یعنی اولین بایت صفره.<br />
خوب این درخواست که بیاد شما باید پاسخ بدید. پاسخ هم ساده هستش:</p>
<pre class="brush: php; title: ; notranslate">
	header(&quot;HTTP/1.0 206 Partial Content&quot;);
	header(&quot;Status: 206 Partial Content&quot;);
	header('Accept-Ranges: bytes');
</pre>
<p>دو تای اولی میگن که اطلاعاتی که قراره با این اتصال فرستاده بشن،‌ یه تیکه از فایل هستن نه یه فایل کامل. خط سوم هم که بالاتر گفتم. البته یادتون باشه header های دیگه مثلا اینها هم باید باشن : </p>
<pre class="brush: php; title: ; notranslate">
	header('Content-type: ' . $mime);
	header('Content-Disposition: attachment; filename=&quot;' . $filename . '&quot;');
	header('Last-Modified: ' . date('D, d M Y H:i:s \G\M\T' , $data_modifed));
</pre>
<p>یا خیلی header های استاندارد دیگه، تو این مثال اولی نوع فایل رو مشخص میکنه مثلا image/jpeg یا application/otect-stream یا &#8230; دومی هم اسم واقعی فایل رو میگه خصوصا اینکه ما داریم فایل رو طوری میفرستیم که آدرسش معلوم نشه، ولی بهتره اسم فایل رو معلوم کنیم که نرم افزار کلاینت یعنی همون دانلود منیجر یا بروزر بفهمه که اسم فایل چیه تا از اسم فایل php مثلا download.php استفاده نکنه.  سومی هم که زمان آخرین دستکاری فایله، و خوب جز اینها باز هم میتونه باشه یه چک بکنید میتونید همه رو تو یه جستجوی ساده توی وب پیدا کنید.<br />
اما حالا باید به کلاینت بگیم که چه بایتهایی رو داریم میفرستیم و چند بایت داریم میفرستیم ، به سه متغییر استفاده شده دقت کنید تو کامنتهای بالای کد نوشتم که هر کدوم چی هست :</p>
<pre class="brush: php; title: ; notranslate">
	//$size : size of file or data (all data not this part)
	//$seek_start : start of data in file, for example in ( Range: bytes=0-500 ) $seek_start=0
	//$seek_end : end of data in file, for example in ( Range: bytes=0-500 ) $seek_end=500
	header(&quot;Content-Range: bytes $seek_start-$seek_end/$size&quot;);
	header(&quot;Content-Length: &quot; . ($seek_end - $seek_start + 1));
</pre>
<p>خوب،‌دیگه header کافیه وقت اطلاعات واقعی هستن که فرستاده بشن. این اطلاعات میتونه هر چی باشه، از دیتابیس باشه، از فایل واقعی باشه یا&#8230; من فرض رو بر فایل واقعی میذارم. خوب ما گفتیم که یه قسمت از فایل رو قراره که بفرستیم نه همه اونو،‌پس وقتشه که شروع کنیم، فایل رو باز کنیم، اون قسمت مورد نظر رو بخونیم، و بعد مستقیم توی خروجی بنویسیم، مثلا با یه echo ساده. البته مشکلی به وجود میاد اونم برای فایلهای بزرگ و رنجهای بزرگ. یعنی مثلا یه فایل ۱ گیگا داری، برنامه دانلود میزنه ۴ قسمت ۲۵۰ مگابایتی درخواست میکنه. خوب اینجا مشکله که کل فایلو یه جا بخونی و بریزی بیرون، چون معمولا PHP برای استفاده از حافظه محدودیت داره. برای رفع این مشکل یه راه هست و اونم اینه که فایل رو تکه تکه بخونی مثل این حالت : </p>
<pre class="brush: php; title: ; notranslate">
	$data_len=$seek_end-$seek_start;
	fseek($file,$seek_start,SEEK_SET);
	$bufsize=2048;

	ignore_user_abort(true);
	@set_time_limit(0);
	while (!(connection_aborted() || connection_status() == 1) &amp;&amp; $data_len &gt; 0){
		if ($data_len &lt; bufsize)
			echo fread($file , $data_len);
		else
			echo fread($file , bufsize);
		$data_len -= $bufsize;
		flush();

	}
</pre>
<p>اون سه تا تابع <a href="http://php.net/manual/en/function.ignore-user-abort.php">ignore_user_abort </a>و <a href="http://php.net/manual/en/function.connection-aborted.php">connection_aborted</a> و  <a href="http://php.net/manual/en/function.connection-status.php">connection_status</a> به ما کمک میکنن که کنترل پایان عمل رو از کاربر بگیریم که برای این مورد اینکار بهترین کاره(یعنی اگه کاربر عمل دانلود رو لغو کنه بلافاصله اسکریپت متوقف نمیشه، ادامه پیدا میکنه تا درست و حسابی متوقف بشه. )‌. از طرفی با <a href="http://php.net/manual/en/function.set-time-limit.php">set_time_limit</a> محدودیت زمان اجرای PHP رو هم از بین میبریم که تو این مورد خیلی مهمه، چون PHP بعد از ۳۰ ثانیه به صورت اتوماتیک متوقف میشه و اگه دانلود زیاد طول بکشه این زیاد جالب نیست. اندازه بافر رو هم ۲۰۴۸ بایت در نظر گرفتم که میشه تغییرش داد. </p>
<p>کد کامل هم میشه این (که البته شما میتونید اونو به صورت یه کلاس دربیارید، من بیشتر قصدم این بود که توضیح بدم همه چیزو نه اینکه یه کلاس کامل بنویسم) </p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
	date_default_timezone_set('GMT');

	//1- file we want to serve :
	$data_file=&quot;/usr/home/f0rud/Desktop/largefile&quot;;
	$data_size=filesize($data_file);
	$mime='application/otect-stream'; //Mime type of file. to begin download its better to use this.
	$filename=basename($data_file); //Name of file, no path included

	//2- Check for request, is the client support this method?
	if (isset($_SERVER['HTTP_RANGE']) || isset($HTTP_SERVER_VARS['HTTP_RANGE'])){
		$ranges_str=(isset($_SERVER['HTTP_RANGE']))?$_SERVER['HTTP_RANGE']:$HTTP_SERVER_VARS['HTTP_RANGE'];
		$ranges_arr=explode('-', substr($ranges_str , strlen('bytes=')));
		//Now its time to check the ranges
		$ranges_arr[0]=intval($ranges_arr[0]);
		if ((intval($ranges_arr[0])&gt;=intval($ranges_arr[1]) &amp;&amp;
			$ranges_arr[1]!=&quot;&quot; &amp;&amp;
			$ranges_arr[0]!=&quot;&quot; ) ||
			($ranges_arr[1]==&quot;&quot; &amp;&amp; $ranges_arr[0]==&quot;&quot;)){
			//Just serve the file normally request is not valid :(
			$ranges_arr[0]=0;
			$ranges_arr[1]=$data_size;
		}
	} else { //The client dose not request HTTP_RANGE so just use the entire file
		$ranges_arr[0]=0;
		$ranges_arr[1]=$data_size;
	}

	//Now its time to serve file
	$file=fopen($data_file,'rb');

	//I use seek and tell to find the location, since I'm too lazy now
	//You may use some + or - instead of all this :)
	if ($ranges_arr[0]==&quot;&quot;){
		//Status 1 : the first one dose not exist
		fseek($file, - intval($ranges_arr[1]),SEEK_END);
		$seek_start=ftell($file);
		fseek($file, intval($ranges_arr[1]),SEEK_CUR);
		$seek_end=ftell($file);
	}elseif ($ranges_arr[1]==&quot;&quot;){
		//Status 2 : the last one dose not exist
		fseek($file,intval($ranges_arr[0]),SEEK_SET);
		$seek_start=ftell($file);
		fseek($file, $data_size - intval($ranges_arr[1]),SEEK_CUR);
		$seek_end=ftell($file);
	}else{
		//Status 3 : Both are here :)
		fseek($file,intval($ranges_arr[0]),SEEK_SET);
		$seek_start=ftell($file);
		fseek($file,  intval($ranges_arr[1])-intval($ranges_arr[0]),SEEK_CUR);
		$seek_end=ftell($file);
	}

	//Lets send headers 

	header('HTTP/1.0 206 Partial Content');
	header('Status: 206 Partial Content');
	header('Accept-Ranges: bytes');

	header('Content-type: ' . $mime);
	header('Content-Disposition: attachment; filename=&quot;' . $filename . '&quot;');
	header(&quot;Content-Range: bytes $seek_start-$seek_end/$data_size&quot;);
	header(&quot;Content-Length: &quot; . ($seek_end - $seek_start));

	//Finally serve data and done ~!
	$data_len=$seek_end - $seek_start;
	fseek($file,$seek_start,SEEK_SET);
	$bufsize=2048;

	ignore_user_abort(true);
	@set_time_limit(0);
	while (!(connection_aborted() || connection_status() == 1) &amp;&amp; $data_len &gt; 0){
		if ($data_len &lt; $bufsize)
			echo fread($file , $data_len);
		else
			echo fread($file , $bufsize);
		$data_len -= $bufsize;
		flush();

	}

	fclose($file);
?&gt;
</pre>
<p>من اینو با <a href="http://www.freedownloadmanager.org/">FDM</a> و <a href="http://www.downthemall.net/">DownThemAll</a> تست کردم. اگه کسی با نرم افزار دیگه تست کرد و جواب داد همینجا بگه. یه چیز عجیب اینه که <a href="http://www.gnu.org/software/wget/">WGET</a> با این کار نمیکنه مدام در مورد Partial Content خطا میده :)‌ به هر حال .<br />
<ins datetime="2011-01-26T13:49:51+00:00">اصلاحیه برای IE8 </ins><br />
دوستی توی <a href="http://cyberrabbits.net/264/download-with-resume-support-in-php/#comment-334">این کامنت نوشتن</a> که این کد با اینترنت اکسپلورر ۸ مشکل داره و علتش هم این باگ هستش : <a href='http://support.microsoft.com/kb/231296' title='Cannot Download .pdf File with HTTP 1.1 Cache-Control = "no-cache" Directive'>Cannot Download .pdf File with HTTP 1.1 Cache-Control = &#8220;no-cache&#8221; Directive</a> </p>
<p>ایشون به عنوان راه حل گفتن که بایستی این دو خط کد هم به Header پاسخ اضافه بشه به عنوان رفع مشکل :‌</p>
<pre class="brush: php; title: ; notranslate">
header(&quot;Cache-Control: no-cache&quot;);
header(&quot;Pragma: no-cache&quot;);
</pre>
<p>این کد باید بین خطوط ۵۸ تا ۶۰ قرار بگیره. فعلا هنوز امکان امتحانشو ندارم. بعد از بررسی دقیقتر حتما اصلاحش رو خواهم نوشت. فعلا اصلا در شرایط نوشتن کد نیستم. بازم ممنون از این دوست.</p>
<div class="plus-one-wrap"><g:plusone href="http://cyberrabbits.net/264/download-with-resume-support-in-php/"></g:plusone></div><p>پستهای مرتبط :<ol>
<li><a href='http://cyberrabbits.net/403/source-forge-redirector/' rel='bookmark' title='دانلود از SourceForge بدون مشکل'>دانلود از SourceForge بدون مشکل</a> <small>اسکریپت رو اگه نصب کردید دوباره آپدیت کنید، چون sf...</small></li>
<li><a href='http://cyberrabbits.net/471/http-redirect/' rel='bookmark' title='HTTP Redirect'>HTTP Redirect</a> <small>یه چند وقتی هست که مدام درگیر کارهای امنیتی، خصوصا...</small></li>
<li><a href='http://cyberrabbits.net/411/mysql-menu-part-3/' rel='bookmark' title='Mysql Menu قسمت سوم'>Mysql Menu قسمت سوم</a> <small>چند وقت پیش در باره منو و طریقه ایجاد آن...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://cyberrabbits.net/264/download-with-resume-support-in-php/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>هاست مجازی بر روی آپاچی</title>
		<link>http://cyberrabbits.net/43/vhosts/</link>
		<comments>http://cyberrabbits.net/43/vhosts/#comments</comments>
		<pubDate>Sat, 12 Dec 2009 17:12:55 +0000</pubDate>
		<dc:creator>فرود</dc:creator>
				<category><![CDATA[آپاچی]]></category>
		<category><![CDATA[خیلی پیش میاد!]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[localhost]]></category>
		<category><![CDATA[virtual host]]></category>
		<category><![CDATA[webserver]]></category>
		<category><![CDATA[هاست مجازی]]></category>
		<category><![CDATA[هاست محلی]]></category>
		<category><![CDATA[وب سرور]]></category>

		<guid isPermaLink="false">http://cyberrabbits.net/?p=43</guid>
		<description><![CDATA[خیلی پیش می آید که ما نیاز به چند آدرس مختلف در یک کامپیوتر داشته باشیم، مثلا نیاز مند این باشیم که کاربران شبکه داخلی، با زدن آی پی کامپیوتر در بروزر خودشان، یک صفحه ببینند و مثلا کاربرانی که از یک شبکه دیگر (مثلا اینترنت) به کامپیوتر شما رجوع میکنند چیز دیگری ببینند و&#8230;
پستهای مرتبط :<ol>
<li><a href='http://cyberrabbits.net/799/apache-speed-up-tips/' rel='bookmark' title='دو نکته برای بالا بردن سرعت &#8211; آپاچی'>دو نکته برای بالا بردن سرعت &#8211; آپاچی</a> <small>از نکاتی که پیشنهاد میشه برای بالا بردن سرعت یه...</small></li>
<li><a href='http://cyberrabbits.net/839/happy-new-year-2/' rel='bookmark' title='سال نو مبارک'>سال نو مبارک</a> <small>اول از همه سال نو مبارک. شروع دهه هم هست...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>خیلی پیش می آید که ما نیاز به چند آدرس مختلف در یک کامپیوتر داشته باشیم، مثلا نیاز مند این باشیم که کاربران شبکه داخلی، با زدن آی پی کامپیوتر در بروزر خودشان، یک صفحه ببینند و مثلا کاربرانی که از یک شبکه دیگر (مثلا اینترنت) به کامپیوتر شما رجوع میکنند چیز دیگری ببینند و اصلا گاهی لازم میشود که شما چندین هاست مجازی مختلف به صورت محلی (Local) بر روی کامپیوتر خود داشته باشید تا بتوانید به صورت کاملا مستقل از هم بر روی هر کدام کار کنید.</p>
<p>برای اینکار آپاچی قابلیت <a href="http://httpd.apache.org/docs/2.2/vhosts/">Virtual Host</a> را پیشنهاد میکند.</p>
<p>برای اینکار ابتدا باید آی پی های مختلف مد نظرتان را مشخص کنید. مثلا من به این آی پی ها نیاز دارم و میخواهم همه آنها به صورت جدا از هم باشند.</p>
<ol>
<li>127.0.0.1 برای استفاده شخصی خودم</li>
<li>192.168.0.1 آدرسی که کاربران شبکه میبینند</li>
<li>78.53.33.13 آی پی من در اینترنت (این آی پی همین طوری و خیلی اتفاقی انتخاب شده :) باور کنید من <a href="http://geotool.flagfox.net/?ip=78.53.33.13&amp;host=78.53.33.13">برلین</a> نیستم و این آی پی من نیست! )</li>
<li>و در نهایت یک سایت محلی دیگر، مجزا از 127.0.0.1</li>
</ol>
<p>برای اینکار، نیازمند ویرایش فایل httpd.conf هستیم .این فایل برای ویندوز در آدرسی هست که آپاچی نصب شده، ولی در لینوکس در /etc/apache2 هست.</p>
<h2>127.0.0.1</h2>
<p>معمولا آدرس 127.0.0.1 را میتوانید هنگام نصب به عنوان آدرس اصلی انتخاب کنید، اگر بنا به هر دلیلی این آدرس در کامپیوتر شما مشکل داشت، دقیقا مثل آدرس چهارم عمل کنید</p>
<h2>192.168.0.1</h2>
<p>برای افزودن این آدرس، کافی است کد زیر را به انتها فایل httpd.conf اضافه کنید :</p>
<pre class="brush: plain; title: ; notranslate">
&lt;VirtualHost 192.168.0.1:80&gt;
    ServerAdmin yourmail@yourhost.ext
    DocumentRoot &quot;c:/path/to/the/root/folder/for/this/host&quot;
    ServerName localnetwork.loc
&lt;/VirtualHost&gt;
</pre>
<p><span id="more-43"></span><br />
ابتدا، باید آی پی مورد نظرتان را انتخاب و پورتی که آپاچی روی آن فعال است را نیز انتخاب کنید. در این مثال 192.168.0.1:80  فقط مطمئن شوید همان پورتی را انتخاب میکنید که آپاچی آن را در اختیار دارد، برای اینکه مطمئن شوید داخل همین فایل دنبال عبارت Listen 80 بگردید (80 ممکن است هر عدد دیگری باشد مثلا 8080 ) این عدد نشانگر پورت مورد استفاده آپاچی است.<br />
بعد آدرس میل ادمین این سایت، برای نمایش در امضای صفحات (معمولا صفحات خطا) سپس پوشه ای که در نظر دارید نقش ریشه این هاست مجازی را داشته باشد، و در نهایت نامی که برای این هاست در نظر گرفته اید، که در این مورد چون روی یک شبکه محلی هستید مهم نیست :) را وارد کنید.<br />
گزینه های دیگر هم هست، و تقریبا تمام تنظیمات مربوط به هاست اصلی هم در این بلاک قابل استفاده خواهد بود.</p>
<h2>78.53.33.13</h2>
<p>برای اینهم دقیقا شبیه بالایی عمل کنید، فقط این آی پی را وارد کنید و مسیر دیگری مربوط به این هاست انتخاب کنید.</p>
<h2>یک هاست محلی دیگر</h2>
<p>خیلی پیش می آید که شما بخواهید دو یا چند هاست مختلف روی کامپیوتر خود داشته باشید، مثلا روی یکی WordPress نصب کنید، دومی یک سیستم دیگر و همین طور الی آخر، البته میتوان از مسیر های داخلی هم استفاده کرد مثلا http://localhost/wordpress ولی من این را نمی پسندم. ویندوز، تمام آی پی های محدوده 127.0.0.x را برای Loop Back (یعنی آی پی که در حقیقت برای Local استفاده میشود ) رزرو کرده است.</p>
<p>برای اینکار، میتوانید از یک آی پی مثل 127.0.0.2 استفاده کنیم ، به این صورت :</p>
<pre class="brush: plain; title: ; notranslate">
&lt;VirtualHost 127.0.0.2:80&gt;
    ServerAdmin yourmail@yourhost.ext
    DocumentRoot &quot;c:/path/to/the/root/folder/for/this/another/host&quot;
    ServerName localnetwork.loc
&lt;/VirtualHost&gt;
</pre>
<p>بعد از این کار، این آدرس، از آدرس قبلی 127.0.0.1 و کلا همه آدرس های دیگر مجزا خواهد بود. اما برای اینکه این آدرس یک نام داشته باشد، مثلا localhost2 چکار کنیم؟<br />
فایل زیر در ویندوز :</p>
<pre class="brush: plain; title: ; notranslate">
%WINDIR%\system32\drivers\etc\hosts
</pre>
<p>و یا فایل زیر در لینوکس :</p>
<pre class="brush: plain; title: ; notranslate">
/etc/hosts
</pre>
<p>را با یک ادیتور متنی مثل Notepad یا <a href="http://notepad-plus.sourceforge.net/uk/site.htm">Notepad++</a> یا هر ادیتور دیگری که دوست دارید، باز کنید. یک خط به این صورت به انتهای آن اضافه کنید :</p>
<pre class="brush: plain; title: ; notranslate">
127.0.0.2		localhost2
</pre>
<p>%WINDIR% پوشه ویندوز شماست و این فایل هم هیچگونه پسوندی ندارد! برای لینوکس و ویندوز سون این فایل رو باید با ویرایشگری که دسترسی ادمین داشته باشه ویرایش کنید.</p>
<p>که به ترتیب آی پی مورد نظر شما با چند فاصله (مهم نیست چند تا، فضای خالی یا کاراکتر تب) و نام مورد نظر شماست. در این صورت میتوانید از این نام جدید هم به صورت محلی استفاده کنید.</p>
<h2>چند نکته مهم :</h2>
<p>برای نامگذاری سایتهای محلی از اسم سایتهای واقعی استفاده نکنید، در این صورت دیگر به هیچ عنوان نمیتوانید آن سایتها را باز کنید! و همیشه سایت محلی باز خواهد شد.</p>
<p>دوم، در صورتی که با باز کردن این هاست های مجازی در مرورگر خود، خطای Forbidden میگیرید، باید پوشه ای را که برای این هاست در نظر گرفته اید را به لیست پوشه های مجاز آپاچی اضافه کنید به این صورت :</p>
<pre class="brush: plain; title: ; notranslate">
&lt;Directory &quot;c:/path/to/the/root/folder/for/this/host&quot;&gt;
    #
    # Possible values for the Options directive are &quot;None&quot;, &quot;All&quot;,
    # or any combination of:
    #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
    #
    # Note that &quot;MultiViews&quot; must be named *explicitly* --- &quot;Options All&quot;
    # doesn't give it to you.
    #
    # The Options directive is both complicated and important.  Please see
    # http://httpd.apache.org/docs/2.2/mod/core.html#options
    # for more information.
    #
    Options Indexes FollowSymLinks Includes ExecCGI

    #
    # AllowOverride controls what directives may be placed in .htaccess files.
    # It can be &quot;All&quot;, &quot;None&quot;, or any combination of the keywords:
    #   Options FileInfo AuthConfig Limit
    #
    AllowOverride All

    #
    # Controls who can get stuff from this server.
    #
    Order allow,deny
    Allow from all

&lt;/Directory&gt;
</pre>
<p>که کامنتها گویای اینکه هر کدام از این گزینه ها چه معنی ای دارند، هست.</p>
<p>::: تازه متوجه شدم که این یکی پست را هم با عبارت خیلی پیش میاد شروع کردم!</p>
<div class="plus-one-wrap"><g:plusone href="http://cyberrabbits.net/43/vhosts/"></g:plusone></div><p>پستهای مرتبط :<ol>
<li><a href='http://cyberrabbits.net/799/apache-speed-up-tips/' rel='bookmark' title='دو نکته برای بالا بردن سرعت &#8211; آپاچی'>دو نکته برای بالا بردن سرعت &#8211; آپاچی</a> <small>از نکاتی که پیشنهاد میشه برای بالا بردن سرعت یه...</small></li>
<li><a href='http://cyberrabbits.net/839/happy-new-year-2/' rel='bookmark' title='سال نو مبارک'>سال نو مبارک</a> <small>اول از همه سال نو مبارک. شروع دهه هم هست...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://cyberrabbits.net/43/vhosts/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

