【问题标题】:Swift: downloadTaskWithURL sometimes "succeeds" with non-nil location even though file does not existSwift:即使文件不存在,downloadTaskWithURL 有时也会以非零位置“成功”
【发布时间】:2025-12-24 07:30:17
【问题描述】:

downloadTaskWithURL 函数有时会为不存在的文件返回非零位置。

测试环境http://192.168.0.102:3000/p/1461224691.mp4处没有文件。

大多数情况下,在此 URL 上调用 downloadTaskWithURL 会导致预期的错误消息:

网络操作期间下载消息时出错。下载地址: http://192.168.0.102:3000/p/1461224691.mp4。地点:无。错误: 可选(错误域=NSURLErrorDomain 代码=-1100 "请求的 URL 在此服务器上找不到。” UserInfo=0x17547b640 {NSErrorFailingURLKey=http://192.168.0.102:3000/p/1461224691.mp4, NSLocalizedDescription=在此未找到请求的 URL 服务器。, NSErrorFailingURLStringKey=http://192.168.0.102:3000/p/1461224691.mp4})

有时,downloadTaskWithURL 以不确定的方式认为文件存在并将某些内容写入location 变量。结果,保护条件没有失败,代码继续执行......它不应该这样做。

fileManager.moveItemAtURL(location!, toURL: fileURL)创建的永久文件只有1个字节,确认网络文件从一开始就不存在。

为什么downloadTaskWithURL 会这样?

func download() {
    // Verify <networkURL>
    guard let downloadURL = NSURL(string: networkURL) where !networkURL.isEmpty else {
        print("Error downloading message: invalid download URL. URL: \(networkURL)")
        return
    }

    // Generate filename for storing locally
    let suffix = (networkURL as NSString).pathExtension
    let localFilename = getUniqueFilename("." + suffix)

    // Create download request
    let task = NSURLSession.sharedSession().downloadTaskWithURL(downloadURL) { location, response, error in
        guard location != nil && error == nil else {
            print("Error downloading message during network operation. Download URL: \(downloadURL). Location: \(location). Error: \(error)")
            return
        }

        // If here, no errors so save message to permanent location
        let fileManager = NSFileManager.defaultManager()
        do {
            let documents = try fileManager.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
            let fileURL = documents.URLByAppendingPathComponent(localFilename)
            try fileManager.moveItemAtURL(location!, toURL: fileURL)
            self.doFileDownloaded(fileURL, localFilename: localFilename)
            print("Downloaded file @ \(localFilename). Download URL: \(downloadURL)")
        } catch {
            print("Error downloading message during save operation. Network URL: \(self.networkURL). Filename: \(localFilename). Error: \(error)")
        }
    }

    // Start download
    print("Starting download @ \(downloadURL)")
    task.resume()
}

【问题讨论】:

    标签: ios swift avfoundation nsurlsession nsurlsessiondownloadtask


    【解决方案1】:

    澄清一下,服务器返回的是 404,但下载任务返回的是一个基本为空的文件?并且您确定服务器实际上返回了错误代码(通过验证服务器日志)?

    无论哪种方式,我都建议检查响应对象中的状态代码。如果不是 200,那么下载任务可能只是下载了错误页面的响应正文。或者,如果状态码为 0,则连接超时。无论哪种方式,都将其视为失败。

    您也可以尝试强制这一切发生在一个线程上,看看不确定性是否消失。

    【讨论】:

    • 谢谢,好主意。会试一试并报告结果!