【问题标题】:Swift - Checking file sizes from a server before downloading is causing a lag in the appSwift - 在下载之前从服务器检查文件大小会导致应用程序延迟
【发布时间】:2020-04-02 03:16:44
【问题描述】:

我有一个服务器,您可以将视频导入到该服务器,上传后应直接下载到应用程序。问题是应用程序将在视频文件完全上传到服务器之前开始下载视频文件。

我设置了一个每 10 秒运行一次的计时器,它会检查文件夹中是否有新视频。如果有新视频,我会使用 URL 会话下载它。如果视频在启动应用程序之前已经上传到服务器,或者视频非常小并且在 10 秒计时器再次运行之前上传,这很好,但这是不切实际的。

我的想法是检查视频大小并在几秒钟后进行比较。如果视频大小相同,则下载它。下面是我用来获取大小并添加到数组中的代码,以便我可以将其与之前的文件大小数组进行比较。

 //videos data array is fetched from the server 

 for video in videos.components(separatedBy: "") {
       if !video.hasPrefix("._"){
           guard let videoUrl = video.encodeUrl() else {return}
           if let url = URL(string:String(self.session.imports_dir + "/" + videoUrl))  {

           //Gets the file size
           let data = NSData(contentsOf: url)
           let fileSize = Double(data!.length)

           videoArrayFileSize.append(fileSize)
  }
 }
}

如果 videoArrayFileSize 与之前的 Filesize 数组不同,则不要下载视频。问题是上面的代码导致应用程序严重滞后,即使我使用

DispatchQueue.global(qos: .background).async 

是否有更好的方法来检查文件大小或其他方法来检查文件是否已完全上传到服务器上?

我无法编辑服务器代码,因此如果可能的话,我喜欢通过应用程序进行编辑。

更新

我尝试使用下面的代码通过 URLSession 获取大小,它适用于测试视频Big Bunny,但不适用于我服务器上的视频。我猜我的视频中的 HEAD 内容长度为空,给出 0。

func getFileSize(_ url: URL, completion: @escaping (Int64, Error?) -> Void){
    let timeoutInterval = 5.0
    var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: timeoutInterval)
    request.httpMethod = "HEAD"

    let group = DispatchGroup()
                 group.enter()


    URLSession.shared.dataTask(with: request) { (data, response, error) in
        let contentLength = response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown
        completion(contentLength, error)
        group.leave()
    }.resume()
}

【问题讨论】:

  • documents 读起来很有趣
  • 更好的解决方案是在服务器上安装一个 API,该 API 以单独调用的形式返回文件的文件大小
  • “我有一个服务器,您可以在上传时将视频导入到该服务器” - 所以,我的下一个想法是,当文件实际上传(完全)时,有服务器生成一个静默通知,提醒应用程序有新文件可供下载
  • NSData(contentsOf: url) 总是耗尽内存imo。如果您不介意,可以使用 AVAsset 类来确定视频的高度和宽度。
  • @MadProgrammer 我问其他开发人员是否可以设置 API 来返回文件大小,但他说他不能,因为我们将文件复制并粘贴到文件夹中。我不确定那是多么真实。

标签: swift xcode download urlsession


【解决方案1】:

解决方案是使用 URL 请求并使用 HTTP 方法“HEAD”。使用“expectedContentLength”,您可以找出文件大小的大小,与前面提到的方法相比,这不会导致延迟。

func getFileSize(_ url: URL, completion: @escaping (Int64, Error?) -> Void){
    let timeoutInterval = 5.0
    var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: timeoutInterval)
    request.httpMethod = "HEAD"

    let group = DispatchGroup()
                 group.enter()

    URLSession.shared.dataTask(with: request) { (data, response, error) in
        let contentLength = response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown
        completion(contentLength, error)
        group.leave()
    }.resume()
}

如果需要,您可以使用下面的代码将大小转换为 MB

let countBytes = ByteCountFormatter()
countBytes.allowedUnits = [.useMB]
countBytes.countStyle = .file
let fileSizeInMB = countBytes.string(fromByteCount: Int64(ENTERYOURVALUEHERE))

【讨论】:

  • 你好,能给我小费吗?例如,当用户想要从 iCloud Drive 上传一些文件时,我必须设置一个限制来选择超过 32MB 的文件。我可以通过此扩展名stackoverflow.com/questions/28268145/get-file-size-in-swift 获取所选文件的大小并获取字符串值“3MB”。如何将所选文件的大小与最大 32MB 进行比较?我试图转换 Int(String) 但它给了我 nil。
  • 我知道这是一种愚蠢的解决方案imgur.com/DNwMCix如果你能以某种方式帮助我,我会很高兴...
猜你喜欢
  • 2016-08-26
  • 1970-01-01
  • 2016-04-15
  • 2012-12-30
  • 1970-01-01
  • 2013-08-28
  • 2021-10-16
  • 2017-09-30
  • 1970-01-01
相关资源
最近更新 更多