<?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>Ankur&#039;s PHP and Javascript blog &#187; HTTP</title>
	<atom:link href="http://www.ankur.com/blog/tag/http/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ankur.com/blog</link>
	<description>PHP and javascript blog</description>
	<lastBuildDate>Tue, 10 Nov 2009 14:28:20 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Resume HTTP downloads in PHP using cURL or fsockopen</title>
		<link>http://www.ankur.com/blog/106/php/resume-http-downloads-php-curl-fsockopen/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=resume-http-downloads-php-curl-fsockopen</link>
		<comments>http://www.ankur.com/blog/106/php/resume-http-downloads-php-curl-fsockopen/#comments</comments>
		<pubDate>Fri, 06 Nov 2009 17:14:29 +0000</pubDate>
		<dc:creator>Ankur Motreja</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[cURL]]></category>
		<category><![CDATA[HTTP]]></category>

		<guid isPermaLink="false">http://www.ankur.com/blog/?p=106</guid>
		<description><![CDATA[This post describes a method to download a file using a PHP script and resume the download if the previous download was interrupted. The code here could be used while downloading a new version of a PHP application from the application author&#8217;s website. Two implementation examples are provided &#8211; one using cURL and another using [...]


Related posts:<ol><li><a href='http://www.ankur.com/blog/68/php/curl-wrapper-class-cli-php-extension-support/' rel='bookmark' title='Permanent Link: cURL wrapper class with executable and PHP extension support'>cURL wrapper class with executable and PHP extension support</a></li><li><a href='http://www.ankur.com/blog/90/php/domain-whois-query-php/' rel='bookmark' title='Permanent Link: Domain name WHOIS query using PHP'>Domain name WHOIS query using PHP</a></li><li><a href='http://www.ankur.com/blog/83/php/javascript-css-compression-yui-compressor-php-gzip/' rel='bookmark' title='Permanent Link: Javascript and CSS compression using YUI compressor, PHP and gzip'>Javascript and CSS compression using YUI compressor, PHP and gzip</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>This post describes a method to download a file using a PHP script and resume the download if the previous download was interrupted. The code here could be used while downloading a new version of a PHP application from the application author&#8217;s website. Two implementation examples are provided &#8211; one using cURL and another using fsockopen.</p>
<p><span id="more-106"></span></p>
<h3>Range header of the HTTP protocol</h3>
<p>First, lets start by seeing how the HTTP protocol allows downloads to be resumed. If you don&#8217;t already have PuTTY, get it from <a rel="nofollow" title="PuTTY" rel="nofollow" href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html" target="_blank">here</a>. We will use PuTTY to directly connect to a HTTP server, send it some HTTP headers and see the response.</p>
<p>Create a text file with some text in it (at least 20 characters long to make it easier for us to test). Upload it so it is accessible at http://localhost/file.txt . I have used the URL http://localhost/file.txt . Change the settings below according to your URL. Open PuTTY and use the following settings:</p>
<p>Host Name: localhost<br />
Port: 80<br />
Connection Type: Raw<br />
Close window on exit: Never</p>
<p>Click on Open. In the window that shows up, type the following:</p>
<pre class="brush: plain;">
GET /file.txt HTTP/1.1
Host: localhost
Range: bytes=5-
Connection: Close
</pre>
<p>Make sure you hit enter twice after typing the text above. You should see something like the text below if you had used something like &#8220;abcdefghijklmnopqrstuvwxyz&#8221; as the contents of file.txt:</p>
<pre class="brush: plain;">
HTTP/1.1 206 Partial Content
Date: Fri, 06 Nov 2009 16:25:07 GMT
Server: Apache/2.2.12 (Win32) mod_ssl/2.2.12 OpenSSL/0.9.8k
Last-Modified: Fri, 06 Nov 2009 15:56:25 GMT
ETag: &quot;4000000044a82-1a-477b5e2d8093c&quot;
Accept-Ranges: bytes
Content-Length: 21
Content-Range: bytes 5-25/26
Connection: close
Content-Type: text/plain

fghijklmnopqrstuvwxyz
</pre>
<p>You can see that it has returned a few headers followed by the contents of the file starting from the 6th byte. Try it a few more times modifying the Range header (for example, 5-15 to get bytes 6 to 16).</p>
<h3>Using cURL to resume downloads</h3>
<p>Resuming a download using cURL is quite straight forward. We use the CURLOPT_RANGE option to set the range if the file we are trying to download already exists and use the &#8220;a&#8221; option to fopen to append the contents to the file. The code is below:</p>
<pre class="brush: php;">
$url=&quot;http://localhost/file.txt&quot;;
$fileName = &quot;file.txt&quot;;

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);

if (file_exists($fileName)) {
	$from = filesize($fileName);
	curl_setopt($ch, CURLOPT_RANGE, $from . &quot;-&quot;);
}

$fp = fopen($fileName, &quot;a&quot;);
if (!$fp) {
	exit;
}
curl_setopt($ch, CURLOPT_FILE, $fp);
$result = curl_exec($ch);
curl_close($ch);

fclose($fp);
</pre>
<h3>Using fsockopen to resume downloads</h3>
<p>Resuming a download with fsockopen is more involved as it requires us to send the request headers and then parse the response headers:</p>
<pre class="brush: php;">
$url=&quot;http://localhost/file.txt&quot;;
$fileName = &quot;file.txt&quot;;

$partialContent = false;
$finalFileSize = 0;

$urlParts = parse_url($url);
$socketHandler = fsockopen($urlParts[&quot;host&quot;], 80, $errno, $errstr, 30);
if (!$socketHandler) {
	exit;
} else {
	$from = 0;

	if (file_exists($fileName)) {
		$from = filesize($fileName);
	}

	$out = &quot;GET &quot; . $urlParts[&quot;path&quot;] . &quot; HTTP/1.1\r\n&quot;;
	$out .= &quot;Host: &quot; . $urlParts[&quot;host&quot;] . &quot;\r\n&quot;;
	$out .= &quot;Range: bytes=&quot; . $from . &quot;-\r\n&quot;;
	$out .= &quot;Connection: Close\r\n\r\n&quot;;

	$headerFound = false;

	if (!$fileHandler = fopen($fileName, &quot;a&quot;)) {
		exit;
	}

	fwrite($socketHandler, $out);
	while (!feof($socketHandler)) {
		if ($headerFound) {
			if ($partialContent) {
				$result = fread($socketHandler, 8192);

				if (fwrite($fileHandler, $result) === false) {
					exit;
				}
			} else {
				fclose($fileHandler);
				fclose($socketHandler);
				exit;
			}
		} else {
			$result = fgets($socketHandler, 8192);
			$result = trim($result);
			if ($result === &quot;&quot;) {
				$headerFound = true;
			}

			if (strstr($result, &quot;206 Partial Content&quot;)) {
				$partialContent = true;
			}

			if (preg_match(&quot;/^Content-Range: bytes (\d+)-(\d+)\/(\d+)$/&quot;, $result, $matches)) {
				$finalFileSize = intval($matches[3]);
			}
		}
	}
	fclose($fileHandler);
	fclose($socketHandler);

	clearstatcache();

	if (filesize($fileName) == $finalFileSize) {
		// success
	} else {
		exit;
	}
}
</pre>


<p>Related posts:<ol><li><a href='http://www.ankur.com/blog/68/php/curl-wrapper-class-cli-php-extension-support/' rel='bookmark' title='Permanent Link: cURL wrapper class with executable and PHP extension support'>cURL wrapper class with executable and PHP extension support</a></li><li><a href='http://www.ankur.com/blog/90/php/domain-whois-query-php/' rel='bookmark' title='Permanent Link: Domain name WHOIS query using PHP'>Domain name WHOIS query using PHP</a></li><li><a href='http://www.ankur.com/blog/83/php/javascript-css-compression-yui-compressor-php-gzip/' rel='bookmark' title='Permanent Link: Javascript and CSS compression using YUI compressor, PHP and gzip'>Javascript and CSS compression using YUI compressor, PHP and gzip</a></li></ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.ankur.com/blog/106/php/resume-http-downloads-php-curl-fsockopen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
