@@ -220,6 +220,7 @@ public extension NextcloudKit {
220220 taskHandler: @escaping ( _ task: URLSessionTask ) -> Void = { _ in } ,
221221 progressHandler: @escaping ( _ totalBytesExpected: Int64 , _ totalBytes: Int64 , _ fractionCompleted: Double ) -> Void = { _, _, _ in } ,
222222 uploaded: @escaping ( _ fileChunk: ( fileName: String , size: Int64 ) ) -> Void = { _ in } ,
223+ assemble: @escaping ( ) -> Void = { } ,
223224 completion: @escaping ( _ account: String , _ filesChunk: [ ( fileName: String , size: Int64 ) ] ? , _ file: NKFile ? , _ error: NKError ) -> Void ) {
224225 guard let nkSession = nkCommonInstance. nksessions. session ( forAccount: account) else {
225226 return completion ( account, nil , nil , . urlError)
@@ -233,7 +234,7 @@ public extension NextcloudKit {
233234 options. customHeader ? [ " Destination " ] = serverUrlFileName. urlEncoded
234235 options. customHeader ? [ " OC-Total-Length " ] = String ( fileNameLocalSize)
235236
236- // check space
237+ // Check available disk space
237238 #if os(macOS)
238239 var fsAttributes : [ FileAttributeKey : Any ]
239240 do {
@@ -266,13 +267,14 @@ public extension NextcloudKit {
266267 #endif
267268
268269 #if os(visionOS) || os(iOS)
269- if freeDisk < fileNameLocalSize * 2 {
270+ if freeDisk < fileNameLocalSize * 3 {
270271 // It seems there is not enough space to send the file
271272 return completion ( account, nil , nil , . errorChunkNoEnoughMemory)
272273 }
273274 #endif
274275
275- func createFolder( completion: @escaping ( _ errorCode: NKError ) -> Void ) {
276+ // Ensure upload chunk folder exists
277+ func createFolderIfNeeded( completion: @escaping ( _ errorCode: NKError ) -> Void ) {
276278 readFileOrFolder ( serverUrlFileName: serverUrlChunkFolder, depth: " 0 " , account: account, options: options) { _, _, _, error in
277279 if error == . success {
278280 completion ( NKError ( ) )
@@ -286,33 +288,46 @@ public extension NextcloudKit {
286288 }
287289 }
288290
289- createFolder { error in
291+ createFolderIfNeeded { error in
290292 guard error == . success else {
291293 return completion ( account, nil , nil , . errorChunkCreateFolder)
292294 }
295+ let outputDirectory = fileChunksOutputDirectory ?? directory
293296 var uploadNKError = NKError ( )
294297
295- let outputDirectory = fileChunksOutputDirectory ?? directory
296- self . nkCommonInstance. chunkedFile ( inputDirectory: directory, outputDirectory: outputDirectory, fileName: fileName, chunkSize: chunkSize, filesChunk: filesChunk) { num in
298+
299+ self . nkCommonInstance. chunkedFile ( inputDirectory: directory,
300+ outputDirectory: outputDirectory,
301+ fileName: fileName,
302+ chunkSize: chunkSize,
303+ filesChunk: filesChunk) { num in
297304 numChunks ( num)
298305 } counterChunk: { counter in
299306 counterChunk ( counter)
300- } completion: { filesChunk in
301- if filesChunk. isEmpty {
302- // The file for sending could not be created
303- return completion ( account, nil , nil , . errorChunkFilesEmpty)
307+ } completion: { filesChunk, error in
308+
309+ // Check chunking error
310+ if let error {
311+ return completion ( account, nil , nil , NKError ( error: error) )
304312 }
313+
314+ guard !filesChunk. isEmpty else {
315+ return completion ( account, nil , nil , NKError ( error: NSError ( domain: " chunkedFile " , code: - 5 , userInfo: [ NSLocalizedDescriptionKey: " Files empty. " ] ) ) )
316+ }
317+
305318 var filesChunkOutput = filesChunk
306319 start ( filesChunkOutput)
307320
308321 for fileChunk in filesChunk {
309322 let serverUrlFileName = serverUrlChunkFolder + " / " + fileChunk. fileName
310323 let fileNameLocalPath = outputDirectory + " / " + fileChunk. fileName
311324 let fileSize = self . nkCommonInstance. getFileSize ( filePath: fileNameLocalPath)
325+
312326 if fileSize == 0 {
313327 // The file could not be sent
314- return completion ( account, nil , nil , . errorChunkFileNull )
328+ return completion ( account, nil , nil , NKError ( error : NSError ( domain : " chunkedFile " , code : - 6 , userInfo : [ NSLocalizedDescriptionKey : " File empty. " ] ) ) )
315329 }
330+
316331 let semaphore = DispatchSemaphore ( value: 0 )
317332 self . upload ( serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, account: account, options: options, requestHandler: { request in
318333 requestHandler ( request)
@@ -359,6 +374,8 @@ public extension NextcloudKit {
359374 let assembleTimeMax : Double = 30 * 60 // 30 min
360375 options. timeout = max ( assembleTimeMin, min ( assembleTimePerGB * assembleSizeInGB, assembleTimeMax) )
361376
377+ assemble ( )
378+
362379 self . moveFileOrFolder ( serverUrlFileNameSource: serverUrlFileNameSource, serverUrlFileNameDestination: serverUrlFileName, overwrite: true , account: account, options: options) { _, _, error in
363380 guard error == . success else {
364381 return completion ( account, filesChunkOutput, nil , . errorChunkMoveFile)
@@ -400,13 +417,9 @@ public extension NextcloudKit {
400417 requestHandler: @escaping ( _ request: UploadRequest ) -> Void = { _ in } ,
401418 taskHandler: @escaping ( _ task: URLSessionTask ) -> Void = { _ in } ,
402419 progressHandler: @escaping ( _ totalBytesExpected: Int64 , _ totalBytes: Int64 , _ fractionCompleted: Double ) -> Void = { _, _, _ in } ,
420+ assemble: @escaping ( ) -> Void = { } ,
403421 uploaded: @escaping ( _ fileChunk: ( fileName: String , size: Int64 ) ) -> Void = { _ in }
404- ) async -> (
405- account: String ,
406- remainingChunks: [ ( fileName: String , size: Int64 ) ] ? ,
407- file: NKFile ? ,
408- error: NKError
409- ) {
422+ ) async -> ( account: String , remainingChunks: [ ( fileName: String , size: Int64 ) ] ? , file: NKFile ? , error: NKError ) {
410423 await withCheckedContinuation { continuation in
411424 uploadChunk ( directory: directory,
412425 fileChunksOutputDirectory: fileChunksOutputDirectory,
@@ -426,13 +439,9 @@ public extension NextcloudKit {
426439 requestHandler: requestHandler,
427440 taskHandler: taskHandler,
428441 progressHandler: progressHandler,
429- uploaded: uploaded) { account, remaining, file, error in
430- continuation. resume ( returning: (
431- account: account,
432- remainingChunks: remaining,
433- file: file,
434- error: error
435- ) )
442+ uploaded: uploaded,
443+ assemble: assemble) { account, remaining, file, error in
444+ continuation. resume ( returning: ( account: account, remainingChunks: remaining, file: file, error: error) )
436445 }
437446 }
438447 }
0 commit comments