如何将video(库中)转换为NSData? 在Swift中

我只是没有“信息”在Swift imagePickerController,所以我不知道如何获取url,并将其转换为数据发送到Web服务。

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) { var videoDataURL = info[UIImagePickerControllerMediaURL] as! NSURL! var videoFileURL = videoDataURL.filePathURL var video = NSData.dataWithContentsOfMappedFile("\(videoDataURL)") } 

Xcode 8.3•Swift 3.1

 func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any]) { let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! if let fileURL = info[UIImagePickerControllerMediaURL] as? URL { do { try FileManager.default.moveItem(at: fileURL, to: documentsDirectoryURL.appendingPathComponent("videoName.mov") print("movie saved") } catch { print(error) } } } 

Swift 2

你应该使用,如果让解开你的select权。 NSData.dataWithContentsOfMappedFile也被弃用iOS8。 尝试使用NSData方法初始化器contentsOfURL:

注意:您还需要将didFinishPickingMediaWithInfo声明从[NSObject : AnyObject]更改为[String : AnyObject]

 func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { if let fileURL = info[UIImagePickerControllerMediaURL] as? NSURL { if let videoData = NSData(contentsOfURL: fileURL) { print(videoData.length) } } } 

正如Rob提到的那样,数据可能非常大,而不是复制文件,您应该将文件移动到文档文件夹中,如下所示:

 let documentsDirectoryURL = try! NSFileManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true) if let fileURL = info[UIImagePickerControllerMediaURL] as? NSURL { do { try NSFileManagerdefaultManager().moveItemAtURL(fileURL, toURL: documentsDirectoryURL.URLByAppendingPathComponent("videoName").URLByAppendingPathExtension("mov")) print("movie saved") } catch { print(error) } } 

有几个问题:

  1. 考虑这一行:

     var videoDataURL = info[UIImagePickerControllerMediaURL] as! NSURL! 

    这会强制展开info[UIImagePickerControllerMediaURL] (这很糟糕,因为如果它是nil ,应用程序会崩溃),并将其转换为隐式解包的可选NSURL! 。 这没有意义。 只要做一个有条件的解包(并解包到NSURL ,而不是NSURL! ):

     if let videoDataURL = info[UIImagePickerControllerMediaURL] as? NSURL { ... } 
  2. 下一行调用filePathURL

     var videoFileURL = videoDataURL.filePathURL 

    如果你想要一个文件的URL,你已经有一个,所以不需要转换,而是使用videoDataURL 。 如果你真的想要一个path,你可以使用path方法:

     let videoPath = videoDataURL.path 

    坦率地说,苹果公司试图将我们从使用stringpath,所以只使用原始的videoDataURL并避免使用pathfilePathURL

  3. 您正在使用dataWithContentsOfMappedFile

     var video = NSData.dataWithContentsOfMappedFile("\(videoDataURL)") 

    如果你真的想使用dataWithContentsOfMappedFile ,正确的Swift语法是:

     let video = NSData(contentsOfMappedFile: videoPath!) 

    dataWithContentsOfMappedFile弃用,所以你应该使用:

     let video = try NSData(contentsOfFile: videoPath!, options: .DataReadingMappedIfSafe) 

    或者,完全绕过videoPath ,您可以:

     let video3 = try NSData(contentsOfURL: videoDataURL, options: .DataReadingMappedIfSafe) 

    很明显,这些try引用应该在一个带有catch块的do块中完成。

  4. 顺便说一下,正如你在上面的例子中所看到的,应该尽可能地使用let

坦率地说,我build议不要把它加载到NSData中。 只要将它复制到NSFileManager ,这是一个更有效的内存使用。 如果video很长,可能会很大,并且应该避免在任何时间将整个内容加载到内存中。

所以你可以:

 if let videoDataURL = info[UIImagePickerControllerMediaURL] as? NSURL { do { // build your destination URL however you want // // let tempFolder = NSURL(fileURLWithPath: NSTemporaryDirectory()) // let destinationURL = tempFolder.URLByAppendingPathComponent("test.mov") // or let documents = try NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false) let destinationURL = documents.URLByAppendingPathComponent("test.mov") // but just copy from the video URL to the destination URL try NSFileManager.defaultManager().copyItemAtURL(videoDataURL, toURL: destinationURL) } catch { print(error) } } 

如果你正在上传到一个Web服务,那么你可以使用NSURLSessionUploadTask ,使用文件或stream选项。 这个请求的构build是一个单独的问题,但是希望你有这样的想法:对于像照片或者特别是video这样的大型资源,如果可以避免的话,不要使用资源实例化NSData