【问题标题】:Swift - Downloading video with downloadTaskWithURLSwift - 使用 downloadTaskWithURL 下载视频
【发布时间】:2016-05-31 22:23:15
【问题描述】:

感谢 downloadTaskWithURL,我正在下载视频,并使用以下代码将其保存到我的画廊:

    func saveVideoBis(fileStringURL:String){

    print("saveVideoBis");

    let url = NSURL(string: fileStringURL);
    (NSURLSession.sharedSession().downloadTaskWithURL(url!) { (location:NSURL?, r:NSURLResponse?, e:NSError?) -> Void in

        let mgr = NSFileManager.defaultManager()

        let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0];

        print(documentsPath);

        let destination = NSURL(string: NSString(format: "%@/%@", documentsPath, url!.lastPathComponent!) as String);

        print(destination);

        try? mgr.moveItemAtPath(location!.path!, toPath: destination!.path!)

        PHPhotoLibrary.requestAuthorization({ (a:PHAuthorizationStatus) -> Void in
            PHPhotoLibrary.sharedPhotoLibrary().performChanges({
                PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(destination!);
                }) { completed, error in
                    if completed {
                        print(error);
                        print("Video is saved!");
                        self.sendNotification();
                    }
            }
        })
    }).resume()
}

它在我的模拟器上运行良好,但在我的 iPad 上,即使出现 print("Video is saved!");,视频也不会保存。 你知道为什么吗?

我的控制台中也出现了该消息

无法从文件创建数据(空)

【问题讨论】:

  • downloadTaskWithURL 方法的completionHandler 部分的文档说“您必须在您的完成处理程序返回之前移动此文件或打开它以供阅读”。现在,您似乎始终都在完成处理程序中,但也许(我在这里猜测)您在完成处理程序中调用另一个方法('performChanges')会搞砸一些事情。您能否在致电performChanges 之前尝试将文件复制到另一个位置?
  • 我对 Swift 比较陌生,你能给我举个例子吗?
  • 你需要一个 NSURL 类型的sourceURL,这就是你的location,然后你需要一个destinationURL,你可以把location 附加到它上面,也许let destination = NSURL(fileURLWithPath: location.absoluteString + "_dest")。一旦你有了,你需要一个NSFileManager类型的fileManager,就像let fileManager = NSFileManager.defaultManager()一样。然后你就可以通过说fileManager.moveItemAtURL(location, toURL: destination) 来移动文件了。该方法throws 所以你需要将它包装在do...try...catch 中。希望这是有道理的
  • 您可以在这里阅读更多关于 NSFileManager 的信息:developer.apple.com/library/ios/documentation/Cocoa/Reference/… NSHipster 的这篇文章也值得一读:nshipster.com/nsfilemanager
  • 你不可能找到答案。您需要了解 absoluteString 和 path 之间的区别。如果您需要本地文件的 url,只需使用 NSURL 初始化器 fileURLWithPath(请注意,absoluteString 具有 file:// 前缀,并且在使用 NSURL fileURLWithPath 初始化器时不能包含它)

标签: ios iphone swift ipad nsurlsessiondownloadtask


【解决方案1】:

请通过代码查看cmets:

Xcode 8 • Swift 3

import UIKit
import Photos

class ViewController: UIViewController {

    func downloadVideoLinkAndCreateAsset(_ videoLink: String) {

        // use guard to make sure you have a valid url
        guard let videoURL = URL(string: videoLink) else { return }

        guard let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }

        // check if the file already exist at the destination folder if you don't want to download it twice
        if !FileManager.default.fileExists(atPath: documentsDirectoryURL.appendingPathComponent(videoURL.lastPathComponent).path) {

            // set up your download task
            URLSession.shared.downloadTask(with: videoURL) { (location, response, error) -> Void in

                // use guard to unwrap your optional url
                guard let location = location else { return }

                // create a deatination url with the server response suggested file name
                let destinationURL = documentsDirectoryURL.appendingPathComponent(response?.suggestedFilename ?? videoURL.lastPathComponent)

                do {

                    try FileManager.default.moveItem(at: location, to: destinationURL)

                    PHPhotoLibrary.requestAuthorization({ (authorizationStatus: PHAuthorizationStatus) -> Void in

                        // check if user authorized access photos for your app
                        if authorizationStatus == .authorized {
                            PHPhotoLibrary.shared().performChanges({
                                PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: destinationURL)}) { completed, error in
                                    if completed {
                                        print("Video asset created")
                                    } else {
                                        print(error)
                                    }
                            }
                        }
                    })

                } catch { print(error) }

            }.resume()

        } else {
            print("File already exists at destination url")
        }

    }

    override func viewDidLoad() {
        super.viewDidLoad()
        downloadVideoLinkAndCreateAsset("https://www.yourdomain.com/yourmovie.mp4")
    }

}

【讨论】:

  • 它工作得很好,谢谢! :) 只有一个小缺点:当我下载一部电影,然后删除它,然后再次尝试下载时,它告诉我“该文件已存在于目标 url”。
  • 您可以删除该条件并使用新名称保存
  • @LeoDabus 你能告诉我如何在这段代码中使用NSURLSessionDownloadDelegate 方法吗?因为它的方法不适用于这段代码?
  • 有没有办法在下载并保存后从照片库中获取该特定资产?
  • @LeoDabus :我使用相同的代码来保存 .m3u8 文件。但是,当尝试保存文件时出现错误,'操作无法完成。 (可可错误-1。)'
【解决方案2】:

如果您想从 URL 下载视频但不想将其存储在图库中。 以下代码对我有用...

 func createDownloadTask(videoURL: String,index: Int) {
    let downloadRequest = NSMutableURLRequest(url: URL(string: videoURL)!)
    let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: OperationQueue.main)
    self.downloadTask = session.downloadTask(with: downloadRequest as URLRequest, completionHandler: { (url, response, error) in
        print("asdasd")
        if error != nil{
            if super.reachability.connection == .none{
                self.showalert(msg: error?.localizedDescription ?? "")
            }else{
                self.downloadTask?.resume()
            }
        }

        guard let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
        // create a deatination url with the server response suggested file name
        let destinationURL = documentsDirectoryURL.appendingPathComponent(response?.suggestedFilename ?? "")

        do {
            if url != nil{
            try FileManager.default.moveItem(at: url!, to: destinationURL)
            }

            }

        } catch { print(error) }

    })
    self.downloadTask!.resume()
}

【讨论】:

  • self.downloadTask 的类型?
  • var downloadTask : URLSessionDownloadTask?
猜你喜欢
  • 2016-11-15
  • 1970-01-01
  • 2014-10-10
  • 2017-10-22
  • 2012-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多