【问题标题】:How to save a downloading file at a specific location so I can read it while downloading in iOS?如何将下载文件保存在特定位置,以便在 iOS 中下载时可以阅读?
【发布时间】:2021-07-09 22:05:38
【问题描述】:

在我的 iOS 项目中,我需要在设备上的特定位置下载一个文件,这样我就可以在它还在下载的同时开始阅读它。

我的目标是从一开始就流式传输音频文件,但我需要将该音频文件保存在本地的最终位置(我不希望在下载过程中将文件保存在临时文件夹中,并且然后在下载完成后移动到其最终位置,这显然是默认行为)。

所以这是我迄今为止尝试过的:


private var observation: NSKeyValueObservation?

func downloadAudioFile()
{
    let url: URL = URL(string: "https://www.demo.com/audiofile.ogg")!
    let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
        if (error != nil)
        {
            print(error)
        }
        else
        {
            print("download complete")
        }
    }
    
    observation = task.progress.observe(\.fractionCompleted) {(progress, _) in
        print("progression : \(progress)")
    }
    
    task.resume()
}

但由于我是 iOS 的初学者,我不知道如何保存下载的数据正在下载。

我怎样才能做到这一点?

谢谢。

【问题讨论】:

  • 也许您可以改为使用 downloadTask 和下载委托方法来接收有关正在接收的数据的定期更新。看看这个委托方法,看起来它在这里很有用:developer.apple.com/documentation/foundation/…
  • @Scriptable 谢谢,是的,它看起来很有趣,但我仍然不明白如何进行这项工作。一个可行的例子会很有帮助。
  • 好的,多亏了这个答案stackoverflow.com/a/54964530/3527024,现在我设法下载文件并在下载期间访问数据。现在我需要知道如何正确地将每个数据块附加到本地文件中。
  • 你可以查看这个答案stackoverflow.com/a/53662203/526828。它写入一个字符串,但它首先将其转换为您已经拥有的Data。所以直接写数据就好了。
  • @matteoh 如果您有一个不错的工作解决方案,我建议您回答自己的问题,以便其他成员可以从您的发现中受益。谢谢你:)

标签: ios swift


【解决方案1】:

好的,这就是我所做的(它可能不是最干净的解决方案,但它有效):

class Downloader : NSObject, URLSessionDelegate, URLSessionDataDelegate
{
    private var session: URLSession!
    private var dataTask: URLSessionDataTask!
    private var fileUrl: URL!

    func download(url: String, fileName: String)
    {
        // get path of directory
        guard let directory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else {
            return
        }
        
        // create file url
        fileUrl = directory.appendingPathComponent(fileName)
        
        // starts download
        session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
        var request: URLRequest = try! URLRequest(url: URL(string: url)!)
        request.cachePolicy = .reloadIgnoringLocalCacheData
        dataTask = session.dataTask(with: request)
        dataTask.resume()
    }

    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
    {
        writeToFile(data: data)
    }

    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse,
                    completionHandler: (URLSession.ResponseDisposition) -> Void)
    {
        completionHandler(URLSession.ResponseDisposition.allow)
    }

    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
    {
        if (error == nil)
        {
            // download complete without any error
        }
        else
        {
            // error during download
        }
    }

    func writeToFile(data: Data)
    {
        // if file exists then write data
        if FileManager.default.fileExists(atPath: fileUrl.path)
        {
            if let fileHandle = FileHandle(forWritingAtPath: fileUrl.path)
            {
                // seekToEndOfFile, writes data at the last of file(appends not override)
                fileHandle.seekToEndOfFile()
                fileHandle.write(data)
                fileHandle.closeFile()
            }
            else
            {
                // Can't open file to write
            }
        }
        else
        {
            // if file does not exist write data for the first time
            do
            {
                try data.write(to: fileUrl, options: .atomic)
            }
            catch
            {
                // Unable to write in new file
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-16
    • 1970-01-01
    • 2020-10-02
    • 1970-01-01
    相关资源
    最近更新 更多