gpt4 book ai didi

ios - Swift - 移动或更新文件失败

转载 作者:行者123 更新时间:2023-11-30 11:57:32 26 4
gpt4 key购买 nike

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

我的下载代码非常基本,我使用Alamofire将文件下载到临时目录中,解压缩它,检查目标目录中是否存在该文件或文件夹,如果找到则将其删除,然后移动新的文件/文件夹到该目录。

但是在检查现有目录并将其删除后很少出现问题。当我尝试将新的文件/文件夹移动到该目录时,出现错误

"File or directory already exists or contents is not empty."

但是在设备目录中失败后检查一下,它显示一个完全正常的目录,没有可能发生冲突的现有文件,或者有时新内容确实像应该的那样移动到目标目录,即使它说失败。这是我最烦恼的。

有人在目录中保存和移动文件时遇到过这种行为吗?

我差点忘了,我正在应用程序支持目录中工作。

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-catch,当它失败时,它基本上是在这个 block 上失败的:

 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)

目标路径是:文件:///var/mobile/Containers/Data/Application/applicationIdAndStuff/Library/Application%20Support/environment/workspace/customers/customer/temp/downloadFileOrFolder

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

所以对我来说问题是文件管理器,它需要很长时间才能完成程序。我真的不想让我的 block 永远处于 sleep 状态,您对如何处理这个问题还有其他想法吗?

最佳答案

我解决了这个问题,只需将代码排序为所需的仅一次任务<每个工件的任务<,以减轻文件管理器的压力。

因此,此代码处理每个工件的下载、解档和移动过程,并且它总是检查更高级别的目录(如果存在),如果不存在则添加它们。对于每一件神器。因此,当多个下载和解档几乎同时完成并开始执行目录操作时,这已经有可能发生冲突。

然后,准备用于移动文件的文件夹会带来更多麻烦而不是帮助。尽管它在大多数情况下都有效,但有时会扰乱移动文件的系统检查,并导致错误告诉我目录或文件已经存在。

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

因为一切都按预期进行。

关于ios - Swift - 移动或更新文件失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47637616/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com