]> source.dussan.org Git - nextcloud-server.git/commitdiff
Chunked upload: Support reusing local chunks
authorBart Visscher <bartv@thisnet.nl>
Fri, 27 Jul 2012 17:02:23 +0000 (19:02 +0200)
committerBart Visscher <bartv@thisnet.nl>
Fri, 27 Jul 2012 17:35:33 +0000 (19:35 +0200)
apps/files/appinfo/filesync.php [new file with mode: 0644]
apps/files/appinfo/info.xml
apps/files/appinfo/version
lib/filechunking.php

diff --git a/apps/files/appinfo/filesync.php b/apps/files/appinfo/filesync.php
new file mode 100644 (file)
index 0000000..707ee24
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+/**
+ * filesync can be called with a PUT method.
+ * PUT takes a stream starting with a 2 byte blocksize,
+ *     followed by binary md5 of the blocks. Everything in big-endian.
+ *     The return is a json encoded with:
+ *       - 'transferid'
+ *       - 'needed' chunks
+ *       - 'last' checked chunk
+ * The URL is made of 3 parts, the service url (remote.php/filesync/), the sync
+ * type and the path in ownCloud.
+ * At the moment the only supported sync type is 'oc_chunked'.
+ * The final URL will look like http://.../remote.php/filesync/oc_chunked/path/to/file
+ */
+
+// only need filesystem apps
+$RUNTIME_APPTYPES=array('filesystem','authentication');
+OC_App::loadApps($RUNTIME_APPTYPES);
+if(!OC_User::isLoggedIn()){
+        if(!isset($_SERVER['PHP_AUTH_USER'])){
+                header('WWW-Authenticate: Basic realm="ownCloud Server"');
+                header('HTTP/1.0 401 Unauthorized');
+                echo 'Valid credentials must be supplied';
+                exit();
+        } else {
+                if(!OC_User::login($_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"])){
+                        exit();
+                }
+        }
+}
+
+list($type,$file) = explode('/', substr($path_info,1+strlen($service)+1), 2);
+
+if ($type != 'oc_chunked') {
+       OC_Response::setStatus(OC_Response::STATUS_NOT_FOUND);
+       die;
+}
+
+if (!OC_Filesystem::is_file($file)) {
+       OC_Response::setStatus(OC_Response::STATUS_NOT_FOUND);
+       die;
+}
+
+switch($_SERVER['REQUEST_METHOD']) {
+       case 'PUT':
+               $input = fopen("php://input", "r");
+               $org_file = OC_Filesystem::fopen($file, 'rb');
+               $info = array(
+                       'name' => basename($file),
+               );
+               $sync = new OC_FileChunking($info);
+               $result = $sync->signature_split($org_file, $input);
+               echo json_encode($result);
+               break;
+       default:
+               OC_Response::setStatus(OC_Response::STATUS_NOT_FOUND);
+}
index 105df092ce59c743bff1b9b115226c761ae4f9b7..e58f83c5a01260969ca8a72c3c8e2c891215c2b2 100644 (file)
@@ -15,5 +15,6 @@
        <remote>
                <files>appinfo/remote.php</files>
                <webdav>appinfo/remote.php</webdav>
+               <filesync>appinfo/filesync.php</filesync>
        </remote>
 </info>
index 1b87bcd0b09c209d6eac67fd268556b35acd1933..e25d8d9f357cfa028ffbf2f7bdc597e28968696b 100644 (file)
@@ -1 +1 @@
-1.1.4
\ No newline at end of file
+1.1.5
index 9aead4c12fb9f94b05553edad8ed0c2439dafcaf..d03af226d8b9a3ddf908b46277e9788a28cdd4b2 100644 (file)
@@ -23,9 +23,8 @@ class OC_FileChunking {
        public function getPrefix() {
                $name = $this->info['name'];
                $transferid = $this->info['transferid'];
-               $chunkcount = $this->info['chunkcount'];
 
-               return $name.'-chunking-'.$transferid.'-'.$chunkcount.'-';
+               return $name.'-chunking-'.$transferid.'-';
        }
 
        protected function getCache() {
@@ -63,4 +62,33 @@ class OC_FileChunking {
                }
                fclose($f);
        }
+
+       public function signature_split($orgfile, $input) {
+               $info = unpack('n', fread($input, 2));
+               $blocksize = $info[1];
+               $this->info['transferid'] = mt_rand();
+               $count = 0;
+               $needed = array();
+               $cache = $this->getCache();
+               $prefix = $this->getPrefix();
+               while (!feof($orgfile)) {
+                       $new_md5 = fread($input, 16);
+                       if (feof($input)) {
+                               break;
+                       }
+                       $data = fread($orgfile, $blocksize);
+                       $org_md5 = md5($data, true);
+                       if ($org_md5 == $new_md5) {
+                               $cache->set($prefix.$count, $data);
+                       } else {
+                               $needed[] = $count;
+                       }
+                       $count++;
+               }
+               return array(
+                       'transferid' => $this->info['transferid'],
+                       'needed' => $needed,
+                       'count' => $count,
+               );
+       }
 }