Browse Source

Use multipartupload for uploading chunks to s3 (#2541)

* WIP

Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>

* Change stepper values

Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>

* Add check

Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>

* WIP

Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>

* Finish

Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>

---------

Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Milen Pivchev 1 year ago
parent
commit
adb2909e05

+ 0 - 1
iOSClient/Data/NCManageDatabase.swift

@@ -350,7 +350,6 @@ class NCManageDatabase: NSObject {
         do {
             let realm = try Realm()
             try realm.write {
-
                 let result = realm.objects(tableChunk.self).filter(NSPredicate(format: "account == %@ AND ocId == %@", account, ocId))
                 realm.delete(result)
             }

+ 20 - 12
iOSClient/Networking/NCNetworkingChunkedUpload.swift

@@ -42,6 +42,7 @@ extension NCNetworking {
         var uploadError = NKError()
 
         var filesNames = NCManageDatabase.shared.getChunks(account: metadata.account, ocId: metadata.ocId)
+
         if filesNames.count == 0 {
             filesNames = NextcloudKit.shared.nkCommonInstance.chunkedFile(inputDirectory: directoryProviderStorageOcId, outputDirectory: directoryProviderStorageOcId, fileName: metadata.fileName, chunkSizeMB: chunkSize)
             if filesNames.count > 0 {
@@ -57,7 +58,13 @@ extension NCNetworking {
             NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": metadata.serverUrl])
         }
 
-        createChunkedFolder(chunkFolderPath: chunkFolderPath, account: metadata.account) { error in
+        let pathServerUrl = CCUtility.returnPathfromServerUrl(metadata.serverUrl, urlBase: metadata.urlBase, userId: metadata.userId, account: metadata.account)!
+        let serverUrlFileNameDestination = metadata.urlBase + "/" + NextcloudKit.shared.nkCommonInstance.dav + "/files/" + metadata.userId + pathServerUrl + "/" + metadata.fileName
+
+        let destinationHeader: [String: String] = ["Destination" : serverUrlFileNameDestination]
+
+        // Create folder for chunks
+        createChunkedFolder(customHeaders: destinationHeader, chunkFolderPath: chunkFolderPath, account: metadata.account) { error in
 
             NCContentPresenter.shared.dismiss(after: NCGlobal.shared.dismissAfterSecond)
 
@@ -71,6 +78,7 @@ extension NCNetworking {
 
             start()
 
+            // Upload the chunks
             for fileName in filesNames {
 
                 let serverUrlFileName = chunkFolderPath + "/" + fileName
@@ -91,7 +99,7 @@ extension NCNetworking {
 
                 let semaphore = DispatchSemaphore(value: 0)
 
-                NextcloudKit.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameChunkLocalPath, requestHandler: { request in
+                NextcloudKit.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameChunkLocalPath, addCustomHeaders: destinationHeader, requestHandler: { request in
 
                     self.uploadRequest[fileNameLocalPath] = request
 
@@ -147,28 +155,28 @@ extension NCNetworking {
                 return
             }
 
-            // Assembling the chunks
+            // Assemble the chunks
             let serverUrlFileNameSource = chunkFolderPath + "/.file"
-            let pathServerUrl = CCUtility.returnPathfromServerUrl(metadata.serverUrl, urlBase: metadata.urlBase, userId: metadata.userId, account: metadata.account)!
-            let serverUrlFileNameDestination = metadata.urlBase + "/" + NextcloudKit.shared.nkCommonInstance.dav + "/files/" + metadata.userId + pathServerUrl + "/" + metadata.fileName
 
-            var customHeader: [String: String] = [:]
+            var customHeaders: [String: String] = [:]
 
             if metadata.creationDate.timeIntervalSince1970 > 0 {
-                customHeader["X-OC-CTime"] = "\(metadata.creationDate.timeIntervalSince1970)"
+                customHeaders["X-OC-CTime"] = "\(metadata.creationDate.timeIntervalSince1970)"
             }
 
             if metadata.date.timeIntervalSince1970 > 0 {
-                customHeader["X-OC-MTime"] = "\(metadata.date.timeIntervalSince1970)"
+                customHeaders["X-OC-MTime"] = "\(metadata.date.timeIntervalSince1970)"
             }
 
+            destinationHeader.forEach { customHeaders[$0] = $1 }
+
             // Calculate Assemble Timeout
             let ASSEMBLE_TIME_PER_GB: Double    = 3 * 60            // 3  min
             let ASSEMBLE_TIME_MIN: Double       = 60                // 60 sec
             let ASSEMBLE_TIME_MAX: Double       = 30 * 60           // 30 min
             let timeout = max(ASSEMBLE_TIME_MIN, min(ASSEMBLE_TIME_PER_GB * fileSizeInGB, ASSEMBLE_TIME_MAX))
 
-            let options = NKRequestOptions(customHeader: customHeader, timeout: timeout, queue: DispatchQueue.global())
+            let options = NKRequestOptions(customHeader: customHeaders, timeout: timeout, queue: DispatchQueue.global())
             
             NextcloudKit.shared.moveFileOrFolder(serverUrlFileNameSource: serverUrlFileNameSource, serverUrlFileNameDestination: serverUrlFileNameDestination, overwrite: true, options: options) { _, error in
 
@@ -223,10 +231,10 @@ extension NCNetworking {
         }
     }
 
-    private func createChunkedFolder(chunkFolderPath: String, account: String, completion: @escaping (_ errorCode: NKError) -> Void) {
+    private func createChunkedFolder(customHeaders: [String : String], chunkFolderPath: String, account: String, completion: @escaping (_ errorCode: NKError) -> Void) {
+
+        let options = NKRequestOptions(customHeader: customHeaders, queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)
 
-        let options = NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)
-        
         NextcloudKit.shared.readFileOrFolder(serverUrlFileName: chunkFolderPath, depth: "0", showHiddenFiles: CCUtility.getShowHiddenFiles(), options: options) { _, _, _, error in
 
             if error == .success {

+ 2 - 3
iOSClient/Settings/CCAdvanced.m

@@ -114,7 +114,8 @@
     [row.cellConfig setObject:[UIFont systemFontOfSize:15.0] forKey:@"textLabel.font"];
     [row.cellConfig setObject:UIColor.labelColor forKey:@"textLabel.textColor"];
     [row.cellConfigAtConfigure setObject:@YES forKey:@"stepControl.wraps"];
-    [row.cellConfigAtConfigure setObject:@1 forKey:@"stepControl.stepValue"];
+
+    [row.cellConfigAtConfigure setObject:@10 forKey:@"stepControl.stepValue"];
     [row.cellConfigAtConfigure setObject:@0 forKey:@"stepControl.minimumValue"];
     [row.cellConfigAtConfigure setObject:@100 forKey:@"stepControl.maximumValue"];
     [section addFormRow:row];
@@ -254,7 +255,6 @@
                             [XLFormOptionsObject formOptionsObjectWithValue:@(90) displayText:NSLocalizedString(@"_3_months_", nil)],
                             [XLFormOptionsObject formOptionsObjectWithValue:@(30) displayText:NSLocalizedString(@"_1_month_", nil)],
                             [XLFormOptionsObject formOptionsObjectWithValue:@(7) displayText:NSLocalizedString(@"_1_week_", nil)],
-                            //[XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:NSLocalizedString(@"_1_day_", nil)],
                             ];
     [sectionSize addFormRow:row];
     
@@ -375,7 +375,6 @@
     }
     
     if ([rowDescriptor.tag isEqualToString:@"chunk"]) {
-        
         NSInteger chunkSize = [[rowDescriptor.value valueData] intValue];
         [CCUtility setChunkSize:chunkSize];
     }

+ 1 - 0
iOSClient/Supporting Files/en.lproj/Localizable.strings

@@ -156,6 +156,7 @@
 "_professional_"            = "Professional";
 "_current_"                 = "Current";
 "_buy_"                     = "Buy";
+"_disabled_"                = "Disabled";
 
 /* MARK: Files lock */
 

+ 7 - 2
iOSClient/Utility/CCUtility.m

@@ -667,19 +667,24 @@
     [UICKeyChainStore setString:sSet forKey:@"accountRequest" service:NCGlobal.shared.serviceShareKeyChain];
 }
 
+/// In megabytes (MB)
 + (NSInteger)getChunkSize
 {
     NSString *size = [UICKeyChainStore stringForKey:@"chunkSize" service:NCGlobal.shared.serviceShareKeyChain];
-    
-    if (size == nil) {
+    NSInteger sizeInt = [size integerValue];
+
+    if (size == nil || sizeInt < 10) {
         return 0;
     } else {
         return [size integerValue];
     }
 }
 
+/// In megabytes (MB)
 + (void)setChunkSize:(NSInteger)size
 {
+    if (size < 10) size = 0;
+
     NSString *sizeString = [@(size) stringValue];
     [UICKeyChainStore setString:sizeString forKey:@"chunkSize" service:NCGlobal.shared.serviceShareKeyChain];
 }