在文档目录下载或移动文件异步 - iOS

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的答案,也可以
随意分享!

Mat*_* Mc 5

有趣的是,这个问题的正确答案被发布在另一个问题中,但它并不是正确的答案。

\n

Apple 的文档中介绍了该解决方案,其中指出:

\n
\n

地点

\n

临时文件的文件 URL。由于该文件是临时文件,因此您必须打开该文件进行读取,或者将其移动到 app\xe2\x80\x99s 沙箱容器目录中的永久位置,然后再从此委托方法返回。

\n

如果您选择打开文件进行读取,则应该在另一个线程中进行实际读取,以避免阻塞委托队列。

\n
\n

您可能正在simpleMove从 DownloadTask 的成功处理程序中调用。当您调用simpleMove后台线程时,成功处理程序将返回,并且您的临时文件在simpleMove调用之前就会被清理。

\n

解决方案是按照Apple所说的操作并打开文件进行读取:

\n
public 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)

希望对你有帮助