NCNetworking+Upload.swift 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. //
  2. // NCNetworking+Upload.swift
  3. // Nextcloud
  4. //
  5. // Created by Marino Faggiana on 07/02/24.
  6. // Copyright © 2024 Marino Faggiana. All rights reserved.
  7. //
  8. // Author Marino Faggiana <marino.faggiana@nextcloud.com>
  9. //
  10. // This program is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. //
  23. import UIKit
  24. import NextcloudKit
  25. import Alamofire
  26. extension NCNetworking {
  27. func upload(metadata: tableMetadata,
  28. uploadE2EEDelegate: uploadE2EEDelegate? = nil,
  29. controller: UIViewController? = nil,
  30. start: @escaping () -> Void = { },
  31. requestHandler: @escaping (_ request: UploadRequest) -> Void = { _ in },
  32. progressHandler: @escaping (_ totalBytesExpected: Int64, _ totalBytes: Int64, _ fractionCompleted: Double) -> Void = { _, _, _ in },
  33. completion: @escaping (_ afError: AFError?, _ error: NKError) -> Void = { _, _ in }) {
  34. let metadata = tableMetadata.init(value: metadata)
  35. var numChunks: Int = 0
  36. let hud = NCHud(controller?.view)
  37. NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Upload file \(metadata.fileNameView) with Identifier \(metadata.assetLocalIdentifier) with size \(metadata.size) [CHUNK \(metadata.chunk), E2EE \(metadata.isDirectoryE2EE)]")
  38. let transfer = NCTransferProgress.Transfer(ocId: metadata.ocId, ocIdTransfer: metadata.ocIdTransfer, session: metadata.session, chunk: metadata.chunk, e2eEncrypted: metadata.e2eEncrypted, progressNumber: 0, totalBytes: 0, totalBytesExpected: 0)
  39. NCTransferProgress.shared.append(transfer)
  40. func tapOperation() {
  41. NotificationCenter.default.postOnMainThread(name: NextcloudKit.shared.nkCommonInstance.notificationCenterChunkedFileStop.rawValue)
  42. }
  43. if metadata.isDirectoryE2EE {
  44. #if !EXTENSION_FILE_PROVIDER_EXTENSION && !EXTENSION_WIDGET
  45. Task {
  46. let error = await NCNetworkingE2EEUpload().upload(metadata: metadata, uploadE2EEDelegate: uploadE2EEDelegate, controller: controller)
  47. completion(nil, error)
  48. }
  49. #endif
  50. } else if metadata.chunk > 0 {
  51. hud.initHudRing(text: NSLocalizedString("_wait_file_preparation_", comment: ""),
  52. tapToCancelDetailText: true,
  53. tapOperation: tapOperation)
  54. uploadChunkFile(metadata: metadata) { num in
  55. numChunks = num
  56. } counterChunk: { counter in
  57. hud.progress(num: Float(counter), total: Float(numChunks))
  58. } start: {
  59. hud.dismiss()
  60. } completion: { account, _, afError, error in
  61. hud.dismiss()
  62. var sessionTaskFailedCode = 0
  63. let directory = self.utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId)
  64. if let error = NextcloudKit.shared.nkCommonInstance.getSessionErrorFromAFError(afError) {
  65. sessionTaskFailedCode = error.code
  66. }
  67. switch error.errorCode {
  68. case NKError.chunkNoEnoughMemory, NKError.chunkCreateFolder, NKError.chunkFilesNull, NKError.chunkFileNull:
  69. self.database.deleteMetadataOcId(metadata.ocId)
  70. self.database.deleteChunks(account: account, ocId: metadata.ocId, directory: directory)
  71. NCContentPresenter().messageNotification("_error_files_upload_", error: error, delay: self.global.dismissAfterSecond, type: .error, afterDelay: 0.5)
  72. case NKError.chunkFileUpload:
  73. if let afError, (afError.isExplicitlyCancelledError || sessionTaskFailedCode == self.global.errorExplicitlyCancelled ) {
  74. self.database.deleteChunks(account: account, ocId: metadata.ocId, directory: directory)
  75. }
  76. case NKError.chunkMoveFile:
  77. self.database.deleteChunks(account: account, ocId: metadata.ocId, directory: directory)
  78. NCContentPresenter().messageNotification("_chunk_move_", error: error, delay: self.global.dismissAfterSecond, type: .error, afterDelay: 0.5)
  79. default: break
  80. }
  81. completion(afError, error)
  82. }
  83. } else if metadata.session == sessionUpload {
  84. let fileNameLocalPath = utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)
  85. uploadFile(metadata: metadata,
  86. fileNameLocalPath: fileNameLocalPath,
  87. controller: controller,
  88. start: start,
  89. progressHandler: progressHandler) { _, _, _, _, _, _, afError, error in
  90. completion(afError, error)
  91. }
  92. } else {
  93. uploadFileInBackground(metadata: metadata, controller: controller, start: start) { error in
  94. completion(nil, error)
  95. }
  96. }
  97. }
  98. func uploadFile(metadata: tableMetadata,
  99. fileNameLocalPath: String,
  100. withUploadComplete: Bool = true,
  101. customHeaders: [String: String]? = nil,
  102. controller: UIViewController?,
  103. start: @escaping () -> Void = { },
  104. requestHandler: @escaping (_ request: UploadRequest) -> Void = { _ in },
  105. progressHandler: @escaping (_ totalBytesExpected: Int64, _ totalBytes: Int64, _ fractionCompleted: Double) -> Void = { _, _, _ in },
  106. completion: @escaping (_ account: String, _ ocId: String?, _ etag: String?, _ date: Date?, _ size: Int64, _ responseData: AFDataResponse<Data?>?, _ afError: AFError?, _ error: NKError) -> Void) {
  107. let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName
  108. let options = NKRequestOptions(customHeader: customHeaders, queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)
  109. NextcloudKit.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: metadata.creationDate as Date, dateModificationFile: metadata.date as Date, account: metadata.account, options: options, requestHandler: { request in
  110. self.database.setMetadataSession(ocId: metadata.ocId,
  111. status: self.global.metadataStatusUploading)
  112. requestHandler(request)
  113. }, taskHandler: { task in
  114. self.database.setMetadataSession(ocId: metadata.ocId,
  115. sessionTaskIdentifier: task.taskIdentifier)
  116. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterUploadStartFile,
  117. object: nil,
  118. userInfo: ["ocId": metadata.ocId,
  119. "ocIdTransfer": metadata.ocIdTransfer,
  120. "session": metadata.session,
  121. "serverUrl": metadata.serverUrl,
  122. "account": metadata.account,
  123. "fileName": metadata.fileName,
  124. "sessionSelector": metadata.sessionSelector])
  125. start()
  126. }, progressHandler: { progress in
  127. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterProgressTask,
  128. object: nil,
  129. userInfo: ["account": metadata.account,
  130. "ocId": metadata.ocId,
  131. "ocIdTransfer": metadata.ocIdTransfer,
  132. "session": metadata.session,
  133. "fileName": metadata.fileName,
  134. "serverUrl": metadata.serverUrl,
  135. "status": NSNumber(value: self.global.metadataStatusUploading),
  136. "progress": NSNumber(value: progress.fractionCompleted),
  137. "totalBytes": NSNumber(value: progress.totalUnitCount),
  138. "totalBytesExpected": NSNumber(value: progress.completedUnitCount)])
  139. progressHandler(progress.completedUnitCount, progress.totalUnitCount, progress.fractionCompleted)
  140. }) { account, ocId, etag, date, size, responseData, afError, error in
  141. var error = error
  142. if withUploadComplete {
  143. if afError?.isExplicitlyCancelledError ?? false {
  144. error = NKError(errorCode: self.global.errorRequestExplicityCancelled, errorDescription: "error request explicity cancelled")
  145. }
  146. self.uploadComplete(metadata: metadata, ocId: ocId, etag: etag, date: date, size: size, error: error)
  147. }
  148. completion(account, ocId, etag, date, size, responseData, afError, error)
  149. }
  150. }
  151. func uploadChunkFile(metadata: tableMetadata,
  152. withUploadComplete: Bool = true,
  153. customHeaders: [String: String]? = nil,
  154. numChunks: @escaping (_ num: Int) -> Void = { _ in },
  155. counterChunk: @escaping (_ counter: Int) -> Void = { _ in },
  156. start: @escaping () -> Void = { },
  157. progressHandler: @escaping (_ totalBytesExpected: Int64, _ totalBytes: Int64, _ fractionCompleted: Double) -> Void = { _, _, _ in },
  158. completion: @escaping (_ account: String, _ file: NKFile?, _ afError: AFError?, _ error: NKError) -> Void) {
  159. let directory = utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId)
  160. let chunkFolder = self.database.getChunkFolder(account: metadata.account, ocId: metadata.ocId)
  161. let filesChunk = self.database.getChunks(account: metadata.account, ocId: metadata.ocId)
  162. var chunkSize = self.global.chunkSizeMBCellular
  163. if networkReachability == NKCommon.TypeReachability.reachableEthernetOrWiFi {
  164. chunkSize = self.global.chunkSizeMBEthernetOrWiFi
  165. }
  166. let options = NKRequestOptions(customHeader: customHeaders, queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)
  167. NextcloudKit.shared.uploadChunk(directory: directory, fileName: metadata.fileName, date: metadata.date as Date, creationDate: metadata.creationDate as Date, serverUrl: metadata.serverUrl, chunkFolder: chunkFolder, filesChunk: filesChunk, chunkSize: chunkSize, account: metadata.account, options: options) { num in
  168. numChunks(num)
  169. } counterChunk: { counter in
  170. counterChunk(counter)
  171. } start: { filesChunk in
  172. start()
  173. self.database.addChunks(account: metadata.account,
  174. ocId: metadata.ocId,
  175. chunkFolder: chunkFolder,
  176. filesChunk: filesChunk)
  177. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterUploadStartFile,
  178. object: nil,
  179. userInfo: ["ocId": metadata.ocId,
  180. "ocIdTransfer": metadata.ocIdTransfer,
  181. "session": metadata.session,
  182. "serverUrl": metadata.serverUrl,
  183. "account": metadata.account,
  184. "fileName": metadata.fileName,
  185. "sessionSelector": metadata.sessionSelector],
  186. second: 0.2)
  187. } requestHandler: { _ in
  188. self.database.setMetadataSession(ocId: metadata.ocId,
  189. status: self.global.metadataStatusUploading)
  190. } taskHandler: { task in
  191. self.database.setMetadataSession(ocId: metadata.ocId,
  192. sessionTaskIdentifier: task.taskIdentifier)
  193. } progressHandler: { totalBytesExpected, totalBytes, fractionCompleted in
  194. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterProgressTask,
  195. object: nil,
  196. userInfo: ["account": metadata.account,
  197. "ocId": metadata.ocId,
  198. "ocIdTransfer": metadata.ocIdTransfer,
  199. "session": metadata.session,
  200. "fileName": metadata.fileName,
  201. "serverUrl": metadata.serverUrl,
  202. "status": NSNumber(value: self.global.metadataStatusUploading),
  203. "chunk": metadata.chunk,
  204. "e2eEncrypted": metadata.e2eEncrypted,
  205. "progress": NSNumber(value: fractionCompleted),
  206. "totalBytes": NSNumber(value: totalBytes),
  207. "totalBytesExpected": NSNumber(value: totalBytesExpected)])
  208. progressHandler(totalBytesExpected, totalBytes, fractionCompleted)
  209. } uploaded: { fileChunk in
  210. self.database.deleteChunk(account: metadata.account,
  211. ocId: metadata.ocId,
  212. fileChunk: fileChunk,
  213. directory: directory)
  214. } completion: { account, _, file, afError, error in
  215. if error == .success {
  216. self.database.deleteChunks(account: account,
  217. ocId: metadata.ocId,
  218. directory: directory)
  219. }
  220. if withUploadComplete {
  221. self.uploadComplete(metadata: metadata, ocId: file?.ocId, etag: file?.etag, date: file?.date, size: file?.size ?? 0, error: error)
  222. }
  223. completion(account, file, afError, error)
  224. }
  225. }
  226. private func uploadFileInBackground(metadata: tableMetadata,
  227. controller: UIViewController?,
  228. start: @escaping () -> Void = { },
  229. completion: @escaping (_ error: NKError) -> Void) {
  230. let metadata = tableMetadata.init(value: metadata)
  231. let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName
  232. let fileNameLocalPath = utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)
  233. start()
  234. // Check file dim > 0
  235. if utilityFileSystem.getFileSize(filePath: fileNameLocalPath) == 0 && metadata.size != 0 {
  236. self.database.deleteMetadataOcId(metadata.ocId)
  237. completion(NKError(errorCode: self.global.errorResourceNotFound, errorDescription: NSLocalizedString("_error_not_found_", value: "The requested resource could not be found", comment: "")))
  238. } else {
  239. if let task = NKBackground(nkCommonInstance: NextcloudKit.shared.nkCommonInstance).upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: metadata.creationDate as Date, dateModificationFile: metadata.date as Date, account: metadata.account, sessionIdentifier: metadata.session) {
  240. NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Upload file \(metadata.fileNameView) with task with taskIdentifier \(task.taskIdentifier)")
  241. self.database.setMetadataSession(ocId: metadata.ocId,
  242. sessionTaskIdentifier: task.taskIdentifier,
  243. status: self.global.metadataStatusUploading)
  244. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterUploadStartFile,
  245. object: nil,
  246. userInfo: ["ocId": metadata.ocId,
  247. "ocIdTransfer": metadata.ocIdTransfer,
  248. "session": metadata.session,
  249. "serverUrl": metadata.serverUrl,
  250. "account": metadata.account,
  251. "fileName": metadata.fileName,
  252. "sessionSelector": metadata.sessionSelector])
  253. completion(NKError())
  254. } else {
  255. self.database.deleteMetadataOcId(metadata.ocId)
  256. completion(NKError(errorCode: self.global.errorResourceNotFound, errorDescription: "task null"))
  257. }
  258. }
  259. }
  260. func uploadComplete(fileName: String,
  261. serverUrl: String,
  262. ocId: String?,
  263. etag: String?,
  264. date: Date?,
  265. size: Int64,
  266. task: URLSessionTask,
  267. error: NKError) {
  268. if let delegate {
  269. return delegate.uploadComplete(fileName: fileName, serverUrl: serverUrl, ocId: ocId, etag: etag, date: date, size: size, task: task, error: error)
  270. }
  271. guard let url = task.currentRequest?.url,
  272. let metadata = self.database.getMetadata(from: url, sessionTaskIdentifier: task.taskIdentifier) else { return }
  273. uploadComplete(metadata: metadata, ocId: ocId, etag: etag, date: date, size: size, error: error)
  274. }
  275. func uploadComplete(metadata: tableMetadata,
  276. ocId: String?,
  277. etag: String?,
  278. date: Date?,
  279. size: Int64,
  280. error: NKError) {
  281. DispatchQueue.main.async {
  282. var isApplicationStateActive = false
  283. #if !EXTENSION
  284. isApplicationStateActive = UIApplication.shared.applicationState == .active
  285. #endif
  286. DispatchQueue.global().async {
  287. let selector = metadata.sessionSelector
  288. if error == .success, let ocId = ocId, size == metadata.size {
  289. NCTransferProgress.shared.clearCountError(ocIdTransfer: metadata.ocIdTransfer)
  290. let metadata = tableMetadata.init(value: metadata)
  291. metadata.uploadDate = (date as? NSDate) ?? NSDate()
  292. metadata.etag = etag ?? ""
  293. metadata.ocId = ocId
  294. metadata.chunk = 0
  295. if let fileId = self.utility.ocIdToFileId(ocId: ocId) {
  296. metadata.fileId = fileId
  297. }
  298. metadata.session = ""
  299. metadata.sessionError = ""
  300. metadata.sessionTaskIdentifier = 0
  301. metadata.status = self.global.metadataStatusNormal
  302. self.database.deleteMetadata(predicate: NSPredicate(format: "ocIdTransfer == %@", metadata.ocIdTransfer))
  303. self.database.addMetadata(metadata)
  304. if selector == self.global.selectorUploadFileNODelete {
  305. self.utilityFileSystem.moveFile(atPath: self.utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocIdTransfer), toPath: self.utilityFileSystem.getDirectoryProviderStorageOcId(ocId))
  306. self.database.addLocalFile(metadata: metadata)
  307. } else {
  308. self.utilityFileSystem.removeFile(atPath: self.utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocIdTransfer))
  309. }
  310. NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Upload complete " + metadata.serverUrl + "/" + metadata.fileName + ", result: success(\(size) bytes)")
  311. let userInfo: [AnyHashable: Any] = ["ocId": metadata.ocId,
  312. "ocIdTransfer": metadata.ocIdTransfer,
  313. "session": metadata.session,
  314. "serverUrl": metadata.serverUrl,
  315. "account": metadata.account,
  316. "fileName": metadata.fileName,
  317. "error": error]
  318. if metadata.isLivePhoto,
  319. NCCapabilities.shared.getCapabilities(account: metadata.account).isLivePhotoServerAvailable {
  320. DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
  321. self.uploadLivePhoto(metadata: metadata, userInfo: userInfo)
  322. }
  323. } else {
  324. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterUploadedFile,
  325. object: nil,
  326. userInfo: userInfo,
  327. second: 0.5)
  328. }
  329. } else {
  330. if error.errorCode == NSURLErrorCancelled || error.errorCode == self.global.errorRequestExplicityCancelled {
  331. NCTransferProgress.shared.clearCountError(ocIdTransfer: metadata.ocIdTransfer)
  332. self.utilityFileSystem.removeFile(atPath: self.utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId))
  333. self.database.deleteMetadataOcId(metadata.ocId)
  334. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterUploadCancelFile,
  335. object: nil,
  336. userInfo: ["ocId": metadata.ocId,
  337. "ocIdTransfer": metadata.ocIdTransfer,
  338. "session": metadata.session,
  339. "serverUrl": metadata.serverUrl,
  340. "account": metadata.account],
  341. second: 0.5)
  342. } else if error.errorCode == self.global.errorBadRequest || error.errorCode == self.global.errorUnsupportedMediaType {
  343. NCTransferProgress.shared.clearCountError(ocIdTransfer: metadata.ocIdTransfer)
  344. self.utilityFileSystem.removeFile(atPath: self.utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId))
  345. self.database.deleteMetadataOcId(metadata.ocId)
  346. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterUploadCancelFile,
  347. object: nil,
  348. userInfo: ["ocId": metadata.ocId,
  349. "ocIdTransfer": metadata.ocIdTransfer,
  350. "session": metadata.session,
  351. "serverUrl": metadata.serverUrl,
  352. "account": metadata.account],
  353. second: 0.5)
  354. if isApplicationStateActive {
  355. NCContentPresenter().showError(error: NKError(errorCode: error.errorCode, errorDescription: "_virus_detect_"))
  356. }
  357. // Client Diagnostic
  358. self.database.addDiagnostic(account: metadata.account, issue: self.global.diagnosticIssueVirusDetected)
  359. } else if error.errorCode == self.global.errorForbidden && isApplicationStateActive {
  360. NCTransferProgress.shared.clearCountError(ocIdTransfer: metadata.ocIdTransfer)
  361. #if !EXTENSION
  362. DispatchQueue.main.async {
  363. let newFileName = self.utilityFileSystem.createFileName(metadata.fileName, serverUrl: metadata.serverUrl, account: metadata.account)
  364. let alertController = UIAlertController(title: error.errorDescription, message: NSLocalizedString("_change_upload_filename_", comment: ""), preferredStyle: .alert)
  365. alertController.addAction(UIAlertAction(title: String(format: NSLocalizedString("_save_file_as_", comment: ""), newFileName), style: .default, handler: { _ in
  366. let atpath = self.utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId) + "/" + metadata.fileName
  367. let toPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId) + "/" + newFileName
  368. self.utilityFileSystem.moveFile(atPath: atpath, toPath: toPath)
  369. self.database.setMetadataSession(ocId: metadata.ocId,
  370. newFileName: newFileName,
  371. sessionTaskIdentifier: 0,
  372. sessionError: "",
  373. status: self.global.metadataStatusWaitUpload,
  374. errorCode: error.errorCode)
  375. }))
  376. alertController.addAction(UIAlertAction(title: NSLocalizedString("_discard_changes_", comment: ""), style: .destructive, handler: { _ in
  377. self.utilityFileSystem.removeFile(atPath: self.utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId))
  378. self.database.deleteMetadataOcId(metadata.ocId)
  379. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterUploadCancelFile,
  380. object: nil,
  381. userInfo: ["ocId": metadata.ocId,
  382. "ocIdTransfer": metadata.ocIdTransfer,
  383. "session": metadata.session,
  384. "serverUrl": metadata.serverUrl,
  385. "account": metadata.account],
  386. second: 0.5)
  387. }))
  388. // Select UIWindowScene active in serverUrl
  389. var controller = UIApplication.shared.firstWindow?.rootViewController
  390. let windowScenes = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }
  391. for windowScene in windowScenes {
  392. if let rootViewController = windowScene.keyWindow?.rootViewController as? NCMainTabBarController,
  393. rootViewController.currentServerUrl() == metadata.serverUrl {
  394. controller = rootViewController
  395. break
  396. }
  397. }
  398. controller?.present(alertController, animated: true)
  399. // Client Diagnostic
  400. self.database.addDiagnostic(account: metadata.account,
  401. issue: self.global.diagnosticIssueProblems,
  402. error: self.global.diagnosticProblemsForbidden)
  403. }
  404. #endif
  405. } else {
  406. NCTransferProgress.shared.clearCountError(ocIdTransfer: metadata.ocIdTransfer)
  407. self.database.setMetadataSession(ocId: metadata.ocId,
  408. sessionTaskIdentifier: 0,
  409. sessionError: error.errorDescription,
  410. status: self.global.metadataStatusUploadError,
  411. errorCode: error.errorCode)
  412. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterUploadedFile,
  413. object: nil,
  414. userInfo: ["ocId": metadata.ocId,
  415. "ocIdTransfer": metadata.ocIdTransfer,
  416. "session": metadata.session,
  417. "serverUrl": metadata.serverUrl,
  418. "account": metadata.account,
  419. "fileName": metadata.fileName,
  420. "error": error],
  421. second: 0.5)
  422. // Client Diagnostic
  423. if error.errorCode == self.global.errorInternalServerError {
  424. self.database.addDiagnostic(account: metadata.account,
  425. issue: self.global.diagnosticIssueProblems,
  426. error: self.global.diagnosticProblemsBadResponse)
  427. } else {
  428. self.database.addDiagnostic(account: metadata.account,
  429. issue: self.global.diagnosticIssueProblems,
  430. error: self.global.diagnosticProblemsUploadServerError)
  431. }
  432. }
  433. }
  434. }
  435. }
  436. }
  437. func uploadProgress(_ progress: Float,
  438. totalBytes: Int64,
  439. totalBytesExpected: Int64,
  440. fileName: String,
  441. serverUrl: String,
  442. session: URLSession,
  443. task: URLSessionTask) {
  444. if let delegate {
  445. return delegate.uploadProgress(progress, totalBytes: totalBytes, totalBytesExpected: totalBytesExpected, fileName: fileName, serverUrl: serverUrl, session: session, task: task)
  446. }
  447. DispatchQueue.global().async {
  448. if let metadata = self.database.getResultMetadataFromFileName(fileName, serverUrl: serverUrl, sessionTaskIdentifier: task.taskIdentifier) {
  449. NotificationCenter.default.postOnMainThread(name: self.global.notificationCenterProgressTask,
  450. object: nil,
  451. userInfo: ["account": metadata.account,
  452. "ocId": metadata.ocId,
  453. "ocIdTransfer": metadata.ocIdTransfer,
  454. "session": metadata.session,
  455. "fileName": metadata.fileName,
  456. "serverUrl": serverUrl,
  457. "status": NSNumber(value: self.global.metadataStatusUploading),
  458. "chunk": metadata.chunk,
  459. "e2eEncrypted": metadata.e2eEncrypted,
  460. "progress": NSNumber(value: progress),
  461. "totalBytes": NSNumber(value: totalBytes),
  462. "totalBytesExpected": NSNumber(value: totalBytesExpected)])
  463. }
  464. }
  465. }
  466. }