Index: wp-includes/class-http.php
===================================================================
--- wp-includes/class-http.php	(revision 17444)
+++ wp-includes/class-http.php	(working copy)
@@ -227,7 +227,9 @@
 			'body' => null,
 			'compress' => false,
 			'decompress' => true,
-			'sslverify' => true
+			'sslverify' => true,
+			'stream' => false,
+			'filename' => null
 		);
 
 		$r = wp_parse_args( $args, $defaults );
@@ -255,6 +257,15 @@
 		$r['local'] = $homeURL['host'] == $arrURL['host'] || 'localhost' == $arrURL['host'];
 		unset( $homeURL );
 
+		if ( $r['stream']  && ! $r['filename'] )
+			$r['filename'] = get_temp_dir() . basename( $url );
+
+		if ( $r['stream'] ) {
+			$r['blocking'] = true;
+			if ( ! is_dir( dirname( $r['filename'] ) ) || ! is_writable( dirname( $r['filename'] ) ) )
+				return new WP_Error( 'http_request_failed', __( 'Destination directory for file streaming does not exist or is not writable.' ) );
+		}
+
 		if ( is_null( $r['headers'] ) )
 			$r['headers'] = array();
 
@@ -748,16 +759,44 @@
 		}
 
 		$strResponse = '';
-		while ( ! feof($handle) )
-			$strResponse .= fread($handle, 4096);
+		$bodyStarted = false;
 
-		fclose($handle);
+		if ( $r['stream'] )
+			$stream_handle = fopen( $r['filename'], 'w+' );
 
+		while ( ! feof($handle) ) {
+			if ( $r['stream'] ) {
+				$block = fread( $handle, 4096 );
+				if ( $bodyStarted ) {
+					fwrite( $stream_handle, $block );
+				} else {
+					$strResponse .= $block;
+					if ( strpos( $strResponse, "\r\n\r\n" ) ) {
+						$process = WP_Http::processResponse( $strResponse );
+						$bodyStarted = true;
+						fwrite( $stream_handle, $process['body'] );
+						unset( $strResponse );
+						$process['body'] = '';
+					}
+				}
+			} else {
+				$strResponse .= fread( $handle, 4096 );
+			}
+		}
+
+		fclose( $handle );
+
 		if ( true === $secure_transport )
 			error_reporting($error_reporting);
 
-		$process = WP_Http::processResponse($strResponse);
-		$arrHeaders = WP_Http::processHeaders($process['headers']);
+		if ( $r['stream'] ) {
+			fclose( $stream_handle );
+			$arrHeaders = WP_Http::processHeaders( $process['headers'] );
+		} else {
+			$process = WP_Http::processResponse( $strResponse );
+			$arrHeaders = WP_Http::processHeaders( $process['headers'] );
+			unset( $strResponse );
+		}
 
 		// Is the response code within the 400 range?
 		if ( (int) $arrHeaders['response']['code'] >= 400 && (int) $arrHeaders['response']['code'] < 500 )
@@ -779,7 +818,7 @@
 		if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($arrHeaders['headers']) )
 			$process['body'] = WP_Http_Encoding::decompress( $process['body'] );
 
-		return array('headers' => $arrHeaders['headers'], 'body' => $process['body'], 'response' => $arrHeaders['response'], 'cookies' => $arrHeaders['cookies']);
+		return array('headers' => $arrHeaders['headers'], 'body' => $process['body'], 'response' => $arrHeaders['response'], 'cookies' => $arrHeaders['cookies'], 'filename' => $r['filename']);
 	}
 
 	/**
@@ -1075,10 +1114,17 @@
 			return array( 'headers' => array(), 'body' => '', 'response' => array('code' => false, 'message' => false), 'cookies' => array() );
 		}
 
-		$strResponse = stream_get_contents($handle);
-		$meta = stream_get_meta_data($handle);
+		if ( $r['stream'] ) {
+			$stream_handle = fopen( $r['filename'], 'w+' );
+			stream_copy_to_stream( $handle, $stream_handle );
+			fclose( $stream_handle );
+			$strResponse = '';
+		} else {
+			$strResponse = stream_get_contents( $handle );
+		}
+		$meta = stream_get_meta_data( $handle );
 
-		fclose($handle);
+		fclose( $handle );
 
 		$processedHeaders = array();
 		if ( isset( $meta['wrapper_data']['headers'] ) )
@@ -1092,7 +1138,7 @@
 		if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($processedHeaders['headers']) )
 			$strResponse = WP_Http_Encoding::decompress( $strResponse );
 
-		return array('headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response'], 'cookies' => $processedHeaders['cookies']);
+		return array('headers' => $processedHeaders['headers'], 'body' => $strResponse, 'response' => $processedHeaders['response'], 'cookies' => $processedHeaders['cookies'], 'filename' => $r['filename']);
 	}
 
 	/**
@@ -1291,6 +1337,8 @@
  */
 class WP_Http_Curl {
 
+	private $headers;
+
 	/**
 	 * Send a HTTP request to a URI using cURL extension.
 	 *
@@ -1387,6 +1435,12 @@
 		else
 			curl_setopt( $handle, CURLOPT_HEADER, false );
 
+		if ( $r['stream'] ) {
+			$stream_handle = fopen( $r['filename'], 'w+' );
+			curl_setopt( $handle, CURLOPT_FILE, $stream_handle );
+			curl_setopt( $handle, CURLOPT_HEADERFUNCTION, array( &$this, 'stream_headers' ) );
+		}
+
 		// The option doesn't work with safe mode or when open_basedir is set.
 		// Disable HEAD when making HEAD requests.
 		if ( !ini_get('safe_mode') && !ini_get('open_basedir') && 'HEAD' != $r['method'] )
@@ -1420,15 +1474,20 @@
 		$theResponse = curl_exec( $handle );
 
 		if ( !empty($theResponse) ) {
-			$headerLength = curl_getinfo($handle, CURLINFO_HEADER_SIZE);
-			$theHeaders = trim( substr($theResponse, 0, $headerLength) );
-			if ( strlen($theResponse) > $headerLength )
-				$theBody = substr( $theResponse, $headerLength );
-			else
+			if ( ! empty( $this->headers ) ) {
+				$theHeaders = $this->headers;
 				$theBody = '';
-			if ( false !== strpos($theHeaders, "\r\n\r\n") ) {
-				$headerParts = explode("\r\n\r\n", $theHeaders);
-				$theHeaders = $headerParts[ count($headerParts) -1 ];
+			} else {
+				$headerLength = curl_getinfo($handle, CURLINFO_HEADER_SIZE);
+				$theHeaders = trim( substr($theResponse, 0, $headerLength) );
+				if ( strlen($theResponse) > $headerLength )
+					$theBody = substr( $theResponse, $headerLength );
+				else
+					$theBody = '';
+				if ( false !== strpos($theHeaders, "\r\n\r\n") ) {
+					$headerParts = explode("\r\n\r\n", $theHeaders);
+					$theHeaders = $headerParts[ count($headerParts) - 1 ];
+				}
 			}
 			$theHeaders = WP_Http::processHeaders($theHeaders);
 		} else {
@@ -1447,6 +1506,9 @@
 
 		curl_close( $handle );
 
+		if ( $r['stream'] )
+			fclose( $stream_handle );
+
 		// See #11305 - When running under safe mode, redirection is disabled above. Handle it manually.
 		if ( !empty($theHeaders['headers']['location']) && (ini_get('safe_mode') || ini_get('open_basedir')) ) {
 			if ( $r['redirection']-- > 0 ) {
@@ -1459,9 +1521,14 @@
 		if ( true === $r['decompress'] && true === WP_Http_Encoding::should_decode($theHeaders['headers']) )
 			$theBody = WP_Http_Encoding::decompress( $theBody );
 
-		return array('headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $response, 'cookies' => $theHeaders['cookies']);
+		return array('headers' => $theHeaders['headers'], 'body' => $theBody, 'response' => $response, 'cookies' => $theHeaders['cookies'], 'filename' => $r['filename']);
 	}
 
+	function stream_headers( $handle, $headers ) {
+		$this->headers .= $headers;
+		return strlen($headers);
+	}
+
 	/**
 	 * Whether this class can be used for retrieving an URL.
 	 *
Index: wp-includes/functions.php
===================================================================
--- wp-includes/functions.php	(revision 17444)
+++ wp-includes/functions.php	(working copy)
@@ -2111,6 +2111,42 @@
 }
 
 /**
+ * Determines a writable directory for temporary files.
+ * Function's preference is to WP_CONTENT_DIR followed by the return value of <code>sys_get_temp_dir()</code>, before finally defaulting to /tmp/
+ *
+ * In the event that this function does not find a writable location, It may be overridden by the <code>WP_TEMP_DIR</code> constant in your <code>wp-config.php</code> file.
+ *
+ * @since 2.5.0
+ *
+ * @return string Writable temporary directory
+ */
+function get_temp_dir() {
+	static $temp;
+	if ( defined('WP_TEMP_DIR') )
+		return trailingslashit(WP_TEMP_DIR);
+
+	if ( $temp )
+		return trailingslashit($temp);
+
+	$temp = WP_CONTENT_DIR . '/';
+	if ( is_dir($temp) && @is_writable($temp) )
+		return $temp;
+
+	if  ( function_exists('sys_get_temp_dir') ) {
+		$temp = sys_get_temp_dir();
+		if ( @is_writable($temp) )
+			return trailingslashit($temp);
+	}
+
+	$temp = ini_get('upload_tmp_dir');
+	if ( is_dir($temp) && @is_writable($temp) )
+		return trailingslashit($temp);
+
+	$temp = '/tmp/';
+	return $temp;
+}
+
+/**
  * Get an array containing the current upload directory's path and url.
  *
  * Checks the 'upload_path' option, which should be from the web root folder,
Index: wp-admin/includes/file.php
===================================================================
--- wp-admin/includes/file.php	(revision 17444)
+++ wp-admin/includes/file.php	(working copy)
@@ -153,42 +153,6 @@
 }
 
 /**
- * Determines a writable directory for temporary files.
- * Function's preference is to WP_CONTENT_DIR followed by the return value of <code>sys_get_temp_dir()</code>, before finally defaulting to /tmp/
- *
- * In the event that this function does not find a writable location, It may be overridden by the <code>WP_TEMP_DIR</code> constant in your <code>wp-config.php</code> file.
- *
- * @since 2.5.0
- *
- * @return string Writable temporary directory
- */
-function get_temp_dir() {
-	static $temp;
-	if ( defined('WP_TEMP_DIR') )
-		return trailingslashit(WP_TEMP_DIR);
-
-	if ( $temp )
-		return trailingslashit($temp);
-
-	$temp = WP_CONTENT_DIR . '/';
-	if ( is_dir($temp) && @is_writable($temp) )
-		return $temp;
-
-	if  ( function_exists('sys_get_temp_dir') ) {
-		$temp = sys_get_temp_dir();
-		if ( @is_writable($temp) )
-			return trailingslashit($temp);
-	}
-
-	$temp = ini_get('upload_tmp_dir');
-	if ( is_dir($temp) && @is_writable($temp) )
-		return trailingslashit($temp);
-
-	$temp = '/tmp/';
-	return $temp;
-}
-
-/**
  * Returns a filename of a Temporary unique file.
  * Please note that the calling function must unlink() this itself.
  *
