Merge pull request #4867 from owncloud/fixing-4546-master

Adding detection of aborted uploads for chunked uploads
This commit is contained in:
Thomas Müller 2013-10-14 06:39:32 -07:00
commit c97b52090e
4 changed files with 75 additions and 19 deletions

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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];