<?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>Web Development Blog &#187; limit</title>
	<atom:link href="http://www.web-development-blog.com/archives/tag/limit/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.web-development-blog.com</link>
	<description>Web development tutorials, SEO articles and PHP script resources</description>
	<lastBuildDate>Sun, 25 Jul 2010 14:38:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Limit the number of downloads per client</title>
		<link>http://www.web-development-blog.com/archives/limit-the-number-of-downloads-per-client/</link>
		<comments>http://www.web-development-blog.com/archives/limit-the-number-of-downloads-per-client/#comments</comments>
		<pubDate>Sat, 05 May 2007 08:14:33 +0000</pubDate>
		<dc:creator>Olaf</dc:creator>
				<category><![CDATA[PHP scripts]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[bandwidth]]></category>
		<category><![CDATA[client]]></category>
		<category><![CDATA[download]]></category>
		<category><![CDATA[limit]]></category>

		<guid isPermaLink="false">http://www.web-development-blog.com/archives/limit-the-number-of-downloads-per-client/</guid>
		<description><![CDATA[These days a customers website has generated a large amount of traffic because a client site has offered some &#8220;bigger&#8221; file downloads to their visitors. Normally there is nothing wrong with this kind of downloads on most of the websites, but in this case there are lot of visitors using a file download manager. With [...]]]></description>
			<content:encoded><![CDATA[<!--S-ButtonZ 1.1.5 Start--><!--S-ButtonZ 1.1.5 End--><p>These days a customers website has generated a large amount of traffic because a client site has offered some &#8220;bigger&#8221; file downloads to their visitors. Normally there is nothing wrong with this kind of downloads on most of the websites, but in this case there are lot of visitors using a file download manager. With the most of these download clients it&#8217;s possible to enter a number of maximum connections for each target server. Just imagine if the visitor is using a value of &#8220;99&#8243; for a file of only 10MB! This way one file download for one visitor will open 99 connections and the used bandwidth will be almost one gigabyte.</p>
<p>There is a apache module name <a href="http://modules.apache.org/search?id=241">mod_limitipconn</a> which can handle this task, but what if the website is on some shared web hosting? In the last situation we need to write some extra function: In this small tutorial we are using some some mod_rewrite rule and a download script while the downloads are logged in a database.<span id="more-96"></span></p>
<p>First we need a database to store the file path, the IP address and the last download time:</p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;"><span style="color: #990099; font-weight: bold;">CREATE</span> <span style="color: #990099; font-weight: bold;">TABLE</span> <span style="color: #990099; font-weight: bold;">IF <span style="color: #CC0099; font-weight: bold;">NOT</span> EXISTS</span> <span style="color: #008000;">`downloaded`</span> <span style="color: #FF00FF;">&#40;</span>
<span style="color: #008000;">`filepath`</span> <span style="color: #999900; font-weight: bold;">varchar</span><span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">255</span><span style="color: #FF00FF;">&#41;</span> <span style="color: #CC0099; font-weight: bold;">NOT</span> <span style="color: #9900FF; font-weight: bold;">NULL</span><span style="color: #000033;">,</span>
<span style="color: #008000;">`ipadres`</span> <span style="color: #999900; font-weight: bold;">varchar</span><span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">15</span><span style="color: #FF00FF;">&#41;</span> <span style="color: #CC0099; font-weight: bold;">NOT</span> <span style="color: #9900FF; font-weight: bold;">NULL</span><span style="color: #000033;">,</span>
<span style="color: #008000;">`last<span style="color: #008080; font-weight: bold;">_</span>access`</span> <span style="color: #999900; font-weight: bold;">datetime</span> <span style="color: #CC0099; font-weight: bold;">NOT</span> <span style="color: #9900FF; font-weight: bold;">NULL</span><span style="color: #000033;">,</span>
<span style="color: #FF9900; font-weight: bold;">UNIQUE</span> <span style="color: #990099; font-weight: bold;">KEY</span> <span style="color: #008000;">`filepath`</span> <span style="color: #FF00FF;">&#40;</span><span style="color: #008000;">`filepath`</span><span style="color: #000033;">,</span><span style="color: #008000;">`ipadres`</span><span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">,</span>
<span style="color: #990099; font-weight: bold;">KEY</span> <span style="color: #008000;">`ipadres`</span> <span style="color: #FF00FF;">&#40;</span><span style="color: #008000;">`ipadres`</span><span style="color: #FF00FF;">&#41;</span>
<span style="color: #FF00FF;">&#41;</span> <span style="color: #990099; font-weight: bold;">ENGINE</span><span style="color: #CC0099;">=</span>MyISAM <span style="color: #990099; font-weight: bold;">DEFAULT</span> <span style="color: #FF9900; font-weight: bold;">CHARSET</span><span style="color: #CC0099;">=</span>latin1<span style="color: #000033;">;</span></pre></div></div>

<p>For example you need to limit the downloads for files in a folder names &#8220;files&#8221;, place the file <strong>.htaccess</strong> file in this folder with this rewrite rule:</p>
<p><code>RewriteEngine on<br />
RewriteRule (.*)(pdf|zip)$ /files/dl.php [QSA]</code></p>
<p>This rule rewrites every file access inside the folder (and sub folders) to the downloader script <strong>dl.php</strong> which is also located in the same folder &#8220;files&#8221;.  Inside the downloader file we need to check if the file was downloaded from the IP address before:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$path</span> <span style="color: #339933;">=</span> <span style="color: #990000;">addslashes</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'REQUEST_URI'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$ip</span> <span style="color: #339933;">=</span> <span style="color: #990000;">addslashes</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'REMOTE_ADDR'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$dl</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #990000;">sprintf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;SELECT UNIX_TIMESTAMP(last_access) last_time FROM downloaded WHERE filepath = '<span style="color: #009933; font-weight: bold;">%s</span>' AND ipadres = '<span style="color: #009933; font-weight: bold;">%s</span>' ORDER BY last_access DESC&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$path</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ip</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$res</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">mysql_num_rows</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$res</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$last_xs</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_result</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$res</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'last_time'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">3600</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$last_xs</span> <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> <span style="color: #990000;">time</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">sprintf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;REPLACE downloaded SET filepath = '<span style="color: #009933; font-weight: bold;">%s</span>', ipadres = '<span style="color: #009933; font-weight: bold;">%s</span>', last_access = NOW()&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$path</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ip</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$dl</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #990000;">sprintf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;REPLACE downloaded SET filepath = '<span style="color: #009933; font-weight: bold;">%s</span>', ipadres = '<span style="color: #009933; font-weight: bold;">%s</span>', last_access = NOW()&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$path</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ip</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$dl</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>We used in this example a time interval of 3600 seconds before it&#8217;s allowed to the user to download the file again. If the boolean variable $dl is &#8220;true&#8221; its allowed to download the file using this PHP code:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$dl</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$fullPath</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'DOCUMENT_ROOT'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #000088;">$path</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$fd</span> <span style="color: #339933;">=</span> <span style="color: #990000;">fopen</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$fullPath</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;r&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$fname</span> <span style="color: #339933;">=</span> <span style="color: #990000;">basename</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fullPath</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Content-type: application/octet-stream'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Content-Disposition: filename=&quot;'</span><span style="color: #339933;">.</span><span style="color: #000088;">$fname</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&quot;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Content-length: '</span><span style="color: #339933;">.</span><span style="color: #990000;">filesize</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fullPath</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Cache-control: private'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">feof</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fd</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$buffer</span> <span style="color: #339933;">=</span> <span style="color: #990000;">fread</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fd</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2048</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$buffer</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #990000;">fclose</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$fd</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #990000;">exit</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'HTTP/1.0 503 Service Unavailable'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Abort, you reached your download limit for this file.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This file download snippet is a very common example from the PHP manual. Notice that if the boolean variable is &#8220;false&#8221; no file download is possible and a forbidden message appears. Download the full code example <a href="http://www.web-development-blog.com/tutorials/limit_file_download.zip">here</a>.<strong>Similar Posts:</strong>
<ul class="similar-posts">
<li><a href="http://www.web-development-blog.com/archives/tutorial-create-a-zip-file-from-folders-on-the-fly/" rel="bookmark" title="September 24, 2007">Tutorial: Create a zip file from folders on the fly</a></li>
<li><a href="http://www.web-development-blog.com/archives/count-clicks-the-right-way/" rel="bookmark" title="February 16, 2009">Count clicks the right way!</a></li>
<li><a href="http://www.web-development-blog.com/archives/upload-images-for-usage-in-tinymce/" rel="bookmark" title="September 25, 2008">Upload images for usage in TinyMCE</a></li>
</ul>
<p><!-- Similar Posts took 3.657 ms --></p>
<div style="clear:both;">&nbsp;</div>]]></content:encoded>
			<wfw:commentRss>http://www.web-development-blog.com/archives/limit-the-number-of-downloads-per-client/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->