diff --git a/lib/private/cache/file.php b/lib/private/cache/file.php
index 2ab914d17b891b421fd573a1ad98edc233d52a99..b0738d2a92ba20e2848729399adea7c2ba71f550 100644
--- a/lib/private/cache/file.php
+++ b/lib/private/cache/file.php
@@ -41,6 +41,24 @@ class File {
 		return $result;
 	}
 
+	/**
+	 * Returns the size of the stored/cached data
+	 *
+	 * @param $key
+	 * @return int
+	 */
+	public function size($key) {
+		$result = 0;
+		$proxyStatus = \OC_FileProxy::$enabled;
+		\OC_FileProxy::$enabled = false;
+		if ($this->hasKey($key)) {
+			$storage = $this->getStorage();
+			$result = $storage->filesize($key);
+		}
+		\OC_FileProxy::$enabled = $proxyStatus;
+		return $result;
+	}
+
 	public function set($key, $value, $ttl=0) {
 		$storage = $this->getStorage();
 		$result = false;
diff --git a/lib/private/connector/sabre/directory.php b/lib/private/connector/sabre/directory.php
index d0334780361444843b0020016ff95fbd9dab8eae..c51f84bf67c7ece5f9c6bf58ba1a8653f7881463 100644
--- a/lib/private/connector/sabre/directory.php
+++ b/lib/private/connector/sabre/directory.php
@@ -71,7 +71,6 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
 		$path = $this->path . '/' . $name;
 		$node = new OC_Connector_Sabre_File($path);
 		return $node->put($data);
-
 	}
 
 	/**
@@ -229,4 +228,5 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
 		}
 		return $props;
 	}
+
 }
diff --git a/lib/private/connector/sabre/file.php b/lib/private/connector/sabre/file.php
index 667f7407f75455b04c5d109b3646861b34b0f1ce..3402946a136b867df5550df582ae8505382c5560 100644
--- a/lib/private/connector/sabre/file.php
+++ b/lib/private/connector/sabre/file.php
@@ -60,23 +60,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
 
 		// chunked handling
 		if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
-
-			list($path, $name) = \Sabre_DAV_URLUtil::splitPath($this->path);
-
-			$info = OC_FileChunking::decodeName($name);
-			if (empty($info)) {
-				throw new Sabre_DAV_Exception_NotImplemented();
-			}
-
-			$chunk_handler = new OC_FileChunking($info);
-			$chunk_handler->store($info['index'], $data);
-			if ($chunk_handler->isComplete()) {
-				$newPath = $path . '/' . $info['name'];
-				$chunk_handler->file_assemble($newPath);
-				return $this->getETagPropertyForPath($newPath);
-			}
-
-			return null;
+			return $this->createFileChunked($data);
 		}
 
 		// mark file as partial while uploading (ignored by the scanner)
@@ -214,4 +198,37 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
 		return \OC\Files\Filesystem::getMimeType($this->path);
 
 	}
+
+	private function createFileChunked($data)
+	{
+		list($path, $name) = \Sabre_DAV_URLUtil::splitPath($this->path);
+
+		$info = OC_FileChunking::decodeName($name);
+		if (empty($info)) {
+			throw new Sabre_DAV_Exception_NotImplemented();
+		}
+		$chunk_handler = new OC_FileChunking($info);
+		$bytesWritten = $chunk_handler->store($info['index'], $data);
+
+		//detect aborted upload
+		if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT' ) {
+			if (isset($_SERVER['CONTENT_LENGTH'])) {
+				$expected = $_SERVER['CONTENT_LENGTH'];
+				if ($bytesWritten != $expected) {
+					$chunk_handler->cleanup();
+					throw new Sabre_DAV_Exception_BadRequest(
+						'expected filesize ' . $expected . ' got ' . $bytesWritten);
+				}
+			}
+		}
+
+		if ($chunk_handler->isComplete()) {
+			$newPath = $path . '/' . $info['name'];
+			$chunk_handler->file_assemble($newPath);
+			return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath);
+		}
+
+		return null;
+	}
+
 }
diff --git a/lib/private/filechunking.php b/lib/private/filechunking.php
index 313a6ee87d2975d6139b2a3a8691a63d6994784e..0dfce696cda7a37057bc853e846a5426477ac653 100644
--- a/lib/private/filechunking.php
+++ b/lib/private/filechunking.php
@@ -34,10 +34,19 @@ class OC_FileChunking {
 		return $this->cache;
 	}
 
+	/**
+	 * Stores the given $data under the given $key - the number of stored bytes is returned
+	 *
+	 * @param $index
+	 * @param $data
+	 * @return int
+	 */
 	public function store($index, $data) {
 		$cache = $this->getCache();
 		$name = $this->getPrefix().$index;
 		$cache->set($name, $data);
+
+		return $cache->size($name);
 	}
 
 	public function isComplete() {
@@ -58,12 +67,24 @@ class OC_FileChunking {
 		$count = 0;
 		for($i=0; $i < $this->info['chunkcount']; $i++) {
 			$chunk = $cache->get($prefix.$i);
-			$cache->remove($prefix.$i);
 			$count += fwrite($f, $chunk);
 		}
+
+		$this->cleanup();
 		return $count;
 	}
 
+	/**
+	 * Removes all chunks which belong to this transmission
+	 */
+	public function cleanup() {
+		$cache = $this->getCache();
+		$prefix = $this->getPrefix();
+		for($i=0; $i < $this->info['chunkcount']; $i++) {
+			$cache->remove($prefix.$i);
+		}
+	}
+
 	public function signature_split($orgfile, $input) {
 		$info = unpack('n', fread($input, 2));
 		$blocksize = $info[1];