2017-12-04 14 views
0

Swift iOS 앱을 사용하여 많은 파일을 다운로드 중이며 내용을 점진적으로 업데이트합니다.Swift - 파일 이동 또는 업데이트가 실패합니다.

, 내가, 파일 또는 폴더가 대상 디렉토리에 존재하는 경우가 확인 압축 해제, 임시 디렉토리에 Alamofire을 사용하여 파일을 다운로드가 발견되면 제거하고 새 파일을 이동 내 다운로드 코드는 아주 기본입니다/해당 디렉토리의 폴더에 있습니다.

그러나 기존 디렉토리를 확인하고 제거한 후에는 거의 문제가 없습니다. 내가 그 디렉토리에 새 파일/폴더을 이동하려고 할 때, 나는

의 오류 "파일 또는 디렉토리가 이미 존재하거나 내용이 비어 있지 않습니다."

그러나 장치 디렉토리에서 오류가 발생했는지 확인했지만 완전히 정밀한 디렉토리가 표시되거나 충돌 할 수있는 기존 파일이 없거나 새로운 내용이 대상 디렉토리로 옮겨지는 경우도 있습니다 그것은 실패했다. 그것이 나를 가장 괴롭히는 것입니다.

디렉토리에 파일을 저장하고 이동할 때 이런 종류의 동작을 경험 한 적이 있습니까?

나는 거의 깜빡하고 있는데, 나는 애플리케이션 지원 디렉토리에서 일하고있다.

internal func loadArtifact(artifact: Artifact, updateClosure: @escaping ((Bool, Int64, Int64, String?) ->())) 
{ 
    let serverpath = artifact.serverpath 
    let name = artifact.name 
    let zipname = artifact.zipname 
    let root = artifact.artifactSetroot 
    let hidden = artifact.artifactSet!.hidden 
    let objectID = artifact.objectID 

    let baseArtifactSet = artifactSetManager.defaultartifactSetManager.getartifactSetDirectory(artifact.artifactSet!) 

    if baseArtifactSet == nil 
    { 
     errorLog("No target directory for artifactSet") 
     return 
    } 
    if name == nil 
    { 
     errorLog("No name for artifact. Can´t save in temp") 
     return 
    } 

    var targetDirectory = baseArtifactSet 
    targetDirectory?.appendPathComponent("temp") 

    targetDirectory?.appendPathComponent(zipname!.replacingOccurrences(of: ".zip", with: "")) 

    let destination: DownloadRequest.DownloadFileDestination = { _, _ in 
     return (targetDirectory!, [.removePreviousFile, .createIntermediateDirectories]) 
    } 


    let url = URL(string: serverpath!) 
    alamofireManager!.download(url!, to: destination).downloadProgress { (progress) in 
     updateClosure(false, progress.completedUnitCount, progress.completedUnitCount, nil) 
     }.responseData { (data) in 
      traceLog("\(data)") 
      if data.response?.statusCode == 200 
      { 
       traceLog("Got an artifact. Will continue to extract itto target position") 
       self.asyncQueue.async { 

        var unzipTarget = baseArtifactSet 


        SSZipArchive.unzipFile(atPath: targetDirectory!.path, toDestination: root ? "\(unzipTarget!.path)/temp/root" : "\(unzipTarget!.path)/temp", progressHandler: { (message, something, progress, max) in 

        }, completionHandler: { (message, finished, error) in 


         let tmpPath = root ? "\(unzipTarget!.path)/temp/root" : "\(unzipTarget!.path)/temp/artifacts/\(zipname!.replacingOccurrences(of: ".zip", with: ""))" 
         let targetPath = root ? unzipTarget!.path : "\(unzipTarget!.path)/artifacts/\(zipname!.replacingOccurrences(of: ".zip", with: ""))" 

         if error == nil && root == false && FileManager.default.fileExists(atPath: targetPath) 
         { 
          do 
          { 
           try FileManager.default.removeItem(atPath: targetPath) 
           traceLog("Deletet old directory at path: \(unzipTarget!.path)") 
          }catch 
          { 
           errorLog("Could not remove directory at path: \(unzipTarget!.path) - \(error)") 
           updateClosure(true,0,0,"Could not remove directory at path: \(unzipTarget!.path) - \(error)") 
          } 


         } 


         do 
         { 

          if FileManager.default.fileExists(atPath: "\(unzipTarget!.path)/artifacts") == false 
          { 
           try FileManager.default.createDirectory(atPath: "\(unzipTarget!.path)/artifacts", withIntermediateDirectories: true, attributes: nil) 
          } 




          if root 
          { 



           do{ 

            let targetDirContent = try FileManager.default.contentsOfDirectory(atPath: targetPath) 
            for file in targetDirContent 
            { 
             if file != "artifacts" && file != "temp" 
             { 
              try FileManager.default.removeItem(atPath: "\(targetPath)/\(file)") 
             } 
            } 



            let files = try FileManager.default.contentsOfDirectory(atPath: tmpPath) 
            for file in files 
            { 
             let fileURL = URL(fileURLWithPath: "\(tmpPath)/\(file)") 
             if fileURL != nil 
             { 
              try FileManager.default.moveItem(atPath: fileURL.path, toPath: "\(targetPath)/\(file)") 
             } 
            } 

            if root && hidden 
            { 
             let deviceInfoString = "var deviceInfo={'platform':'iOS'}" 

             if FileManager.default.fileExists(atPath: "\(targetPath)/deviceInfo.js") 
             { 
              try FileManager.default.removeItem(atPath: "\(targetPath)/deviceInfo.js") 
             } 

            } 

           } 
           catch{ 
            errorLog("Error while enumerating files in temp root directory: \(error)") 
            updateClosure(true,0,0,"Error while enumerating files in temp root directory: \(error)") 

           } 

          }else 
          { 
           if FileManager.default.fileExists(atPath: targetPath) 
           { 
            debugLog("Deleting: \(targetPath)") 
            try FileManager.default.removeItem(atPath: targetPath) 
           }else 
           { 
            debugLog("Creating: \(targetPath)") 

           } 


           debugLog("Trying to move") 
           try FileManager.default.moveItem(atPath: tmpPath, toPath: targetPath) 

          } 


         }catch 
         { 
          errorLog("Could not move directory for artifact: \(unzipTarget!.path) - \(error)") 
          updateClosure(true,0,0,"Could not move directory for artifact: \(unzipTarget!.path) - \(error)") 
         } 




         try FileManager.default.removeItem(atPath: targetDirectory!.path) 

         self.asyncQueue.async (flags: .barrier) { 

          let ownContext = MyStorageClient.defaultManager.newBackgroundWorkerMOC() 
          let ownArtifact = ownContext.object(with: objectID) as! Artifact 

          ownArtifact.state = ArtifactState.Ready.rawValue 
          ownArtifact.updateAvaiable = false 

          if root == true && ownArtifact.artifactSet?.state == artifactSetState.Initialised.rawValue 
          { 
           ownArtifact.artifactSet?.state = artifactSetState.Created.rawValue 
          } 


          do{ 
           try ownContext.save() 

           updateClosure(true, 0,0,nil) 

          }catch{ 
           errorLog("Error while saving artifact context") 

           updateClosure(true, 0,0, "Error while saving context after artifact Update. \(error)") 
          } 

         } 
        }) 

       } 
      }else 
      { 

       errorLog("Something went wrong downloading an artifact: \(data.response)") 
       updateClosure(true,0,0,"Something went wrong downloading an artifact: \(data.response)") 

      } 
    } 


} 

아무에게도 왜 실패하고 있는지 말할 수 있습니까? 나는 시도 라인의 대부분의 주위에 - - 캐치를 시도 할 추가, 그것이 실패했을 때, 그것은 기본적으로이 덩어리에 실패 :

if FileManager.default.fileExists(atPath: targetPath) 
{ 
    debugLog("Deleting: \(targetPath)") 
    try FileManager.default.removeItem(atPath: targetPath) 
}else 
{ 
    debugLog("Creating: \(targetPath)") 

} 


    debugLog("Trying to move") 
    try FileManager.default.moveItem(atPath: tmpPath, toPath: targetPath) 

있는 TargetPath은 다음과 같습니다 파일 : /// VAR/모바일/용기/데이터/응용 프로그램/applicationIdAndStuff/라이브러리/응용 프로그램 % 20Support/환경/작업 공간/고객/고객/온도/downloadFileOrFolder

또 다른 갱신 : 나는 코드를 변경, 그래서 이전 파일은 백업 폴더로 이동하는 대신 삭제됩니다 바로 주소를 변경하는 것이 파일을 완전히 삭제하는 것보다 빠르다고 생각했기 때문입니다. 잘못된. 이제 오류는 이전보다 더 자주 발생합니다.

나를 위해 문제는 FileManager를 참조하므로 절차를 완료하는 데 너무 오래 걸립니다. 나는 정말로 내 블록을 언제든지 잠자기하고 싶지 않습니다. 어떻게이 문제를 해결할 수 있는지에 대한 아이디어가 있습니까?

+0

코드를 작게 만들 수 있습니까? 나는 그 모든 것을 읽기에는 너무 게으름입니다. – zombie

+0

전체 코드 맨 위에 문제가있는 부분 아래에 업데이트되었습니다. –

+0

@Viktor_DE, 런타임에서'targetPath'의 값은 무엇입니까? – holex

답변

0

나는 단지 파일 관리자에서 압력을 받아 각 유물 <에 대한 작업 < 및 > 작업 후> 단순히 필요한 에 코드를 정렬하여 문제를 알아 냈어.

이 코드는 각 이슈에 대한 다운로드 및 보관 취소 및 이동 프로세스를 처리하며 존재하는 경우 항상 상위 레벨의 디렉토리를 검사하고 그렇지 않은 경우 추가합니다. 각 이슈마다. 이렇게하면 이미 둘 이상의 다운로드와 아카이브 해제가 거의 동시에 완료되고 디렉토리 항목을 수행하기 시작할 때 충돌이 발생할 수 있습니다.

그런 다음 이동 파일을위한 폴더를 준비하여 도움이되는 것보다 많은 문제를 만들었습니다. 대부분의 경우 작동하지만 때때로 시스템 검사를 망쳐 놓아 파일을 이동 시키므로 디렉토리 또는 파일이 이미 있음을 알리는 오류가 발생합니다.

파일에 대한 각 loadArtifact를 가져 오기 전에 루프에서 반복 검사를 방지하기 위해 필요한 디렉토리를 재설정하고 상위 디렉토리를 만듭니다.

예상대로 작동합니다.