Swift - 移动或更新文件失败

时间:2017-12-04 16:19:22

标签: ios swift alamofire

我使用Swift iOS应用程序下载大量文件,并对内容使用增量更新。

我的下载代码非常基本,我使用 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)")

            }
    }


}

那么,任何人都可以告诉我,为什么会失败? 我在大多数try行中添加了do-try-catches,当它失败时,它基本上在这个块上失败了:

 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 /库/ Application%20Support /环境/工作区/客户/客户/温度/ downloadFileOrFolder

另一个更新: 我更改了代码,因此旧文件将被移动到备份文件夹而不是立即删除,因为我认为更改地址应该比完全删除文件更快。错误。现在错误比以前更频繁地发生。

所以对我来说问题是指FileManager,完成程序需要很长时间。我真的不想让我的座位随时睡觉,你对如何处理这个问题有另一个想法吗?

1 个答案:

答案 0 :(得分:0)

我找出了问题,只需将代码排序到所需的>只需一次任务< >任务为每个工件< 来减轻压力文件管理。

因此,此代码处理每个工件的下载和取消存档以及移动过程,并且它始终检查更高级别上的目录(如果存在),如果不存在则添加它们。对于每个神器。 因此,当多个下载和取消归档几乎同时完成并开始执行目录时,这已经存在冲突的可能性。

然后,通过准备移动文件的文件夹比它帮助更麻烦。 虽然它大部分时间都可以工作,但它有时会弄乱系统检查以移动文件并导致错误,告诉我目录或文件已经存在。

因此,在获取文件的每个loadArtifact之前,我重置所需的目录并创建更高级别的目录,以防止在循环中重复检查。

因为这一切都像预期的那样。