Mad*_*ios 10 asynchronous download nsfilemanager ios nsurlsession
我正在构建一个iOS应用程序,用户可以在其中下载不同的文件.
我正在使用an URLSessionDownloadTask
和an URLSession
异步下载文件.
下载完成后,目标文件夹默认为tmp/
目录.
因此,当下载结束时,我需要将临时文件移动到另一个目录.
对于图片或歌曲,这只需要1秒甚至更短.
但是,当文件是视频时,最多可能需要15秒.
为了让用户仍然可以与应用程序进行交互,我想让这个移动异步.
每次我尝试这样做时,文件管理器都会抛出异常.
"CFNetworkDownload_xxxxxx.tmp"无法移动到"下载",因为前者不存在,或者包含后者的文件夹不存在.
我试图在后台线程中调用文件管理器,它会抛出.
我尝试在调用move方法之前删除目标文件,以确保该文件尚不存在.
copy
在从tmp/
目录中删除文件之前,我尝试调用该函数.
对文件管理器的调用看起来像那样.
func simpleMove(from location: URL, to dest: URL) -> Bool {
let fileManager = FileManager.default
do {
try fileManager.moveItem(at: location, to: dest)
return true
} catch {
print("\(error.localizedDescription)")
return false
}
}
Run Code Online (Sandbox Code Playgroud)
当我把它放在后台线程中时,我这样做.
DispatchQueue.global().async {
if !simpleMove(from: location, to: dest) {
//Failure
}
}
Run Code Online (Sandbox Code Playgroud)
如何在不影响UI的情况下移动真正大的文件?
将文件直接下载到永久目录中是一种更好的解决方案.我怎样才能做到这一点?
当我simpleMove(from:to:)
同步拨打电话时,它完美无缺.
那么,为什么错误说目标目录不存在?(或类似的东西,我不确定该错误的含义)
谢谢.
上面的代码是用Swift 3编写的,但是如果你有Objective-C或Swift 2的答案,也可以
随意分享!
有趣的是,这个问题的正确答案被发布在另一个问题中,但它并不是正确的答案。
\nApple 的文档中介绍了该解决方案,其中指出:
\n\n\n地点
\n临时文件的文件 URL。由于该文件是临时文件,因此您必须打开该文件进行读取,或者将其移动到 app\xe2\x80\x99s 沙箱容器目录中的永久位置,然后再从此委托方法返回。
\n如果您选择打开文件进行读取,则应该在另一个线程中进行实际读取,以避免阻塞委托队列。
\n
您可能正在simpleMove
从 DownloadTask 的成功处理程序中调用。当您调用simpleMove
后台线程时,成功处理程序将返回,并且您的临时文件在simpleMove
调用之前就会被清理。
解决方案是按照Apple所说的操作并打开文件进行读取:
\npublic func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {\n do {\n let file: FileHandle = try FileHandle(forReadingFrom: location)\n \n DispatchQueue.global().async {\n let data = file.readDataToEndOfFile()\n FileManager().createFile(atPath: destination, contents: data, attributes: nil)\n }\n } catch {\n // Handle error\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
vp2*_*698 -1
我遇到了同样的问题,但我解决了。
首先检查该文件是否存在于该路径中,因为我遇到了问题,因为路径扩展名与位置 URL 不同。我试图重命名音频,但路径扩展名不同(例如 mp3 到 m4a)
此外,如果目标路径中已存在任何其他文件,则会出现此问题。
因此,首先尝试检查文件是否存在于您使用的位置
let fileManager = FileManager.default
if fileManager.fileExists(atPath: location.path) {
do {
try fileManager.moveItem(at: location, to: dest)
return true
} catch {
print("\(error.localizedDescription)")
return false
}
}
Run Code Online (Sandbox Code Playgroud)
希望对你有帮助
归档时间: |
|
查看次数: |
981 次 |
最近记录: |