2017-12-04 8 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 /モバイル/コンテナ/ Data/Application/applicationIdAndStuff/Library/Application%20Support/environment/workspace/customers/customer/temp/downloadFileOrFolder

別のアップデート: コードを変更したので、古いファイルは削除されずにバックアップフォルダに移動さ​​れます。私はアドレスを変更するほうがファイルを完全に削除するよりも速くなければならないと考えていたからです。違う。今度はエラーが以前よりも頻繁に発生します。

私の問題はFileManagerを参照しているため、手順を完了するのに時間がかかりすぎます。私はいつも私のブロックをいつでも寝たいと思っていません。あなたはこの問題をどう扱うかという別のアイディアを持っていますか?

+0

あなたは、私が問題である部分の下に、完全なコード上に、更新した – zombie

+0

のすべてを読むのが面倒だ、少ないコードを作ることができます。 –

+0

@Viktor_DE、実行時の 'targetPath'の値は何ですか? – holex

答えて

0

私は単純にのみFileManagerの上の圧力をテイクダウンするために、各アーティファクト<ためのタスク<と>タスクたら>必要なにコードをソートすることによって、問題を考え出しました。

このコードは、各アーティファクトのダウンロードと保存解除および移動のプロセスを処理し、存在する場合は常に上位レベルのディレクトリをチェックし、存在しない場合は追加します。各アーティファクトごとに。 これはすでに複数のダウンロードとアーカイブ解除がほぼ同時に終了し、ディレクトリの処理を開始したときの競合の可能性がありました。

次に、ファイルを移動するためのフォルダを準備することで、それは助けたよりも多くのトラブルを起こしました。 それはほとんどの時間動作しますが、それは時々、システムがファイルを移動するためにチェック台無しにし、ディレクトリやファイルがすでに存在していることを私に言って、エラーが発生します。

だからファイルに対してそれぞれloadArtifactに入る前に、私は必要なディレクトリをリセットし、ループ内で繰り返しチェックを防ぐために、より高いレベルのディレクトリを作成します。予想されるようなそのすべての作品以来

関連する問題