Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/101.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何将视频(在多媒体资料中)转换为NSData?迅速地_Ios_Swift_Swift3 - Fatal编程技术网

Ios 如何将视频(在多媒体资料中)转换为NSData?迅速地

Ios 如何将视频(在多媒体资料中)转换为NSData?迅速地,ios,swift,swift3,Ios,Swift,Swift3,我只是在Swift imagePickerController中没有“信息”,所以我不知道如何获取url并将其转换为数据发送到web服务 func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) { var videoDataURL = info[UIImagePickerControllerMediaURL]

我只是在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 10•Swift 4.2或更高版本

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

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

您应该使用if let打开您的选项。另外,
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所述,数据可能非常大,但不应复制文件,而应将文件移动到documents文件夹,如下所示:

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)
    }
}

有几个问题:

  • 以这一行为例:

    var videoDataURL = info[UIImagePickerControllerMediaURL] as! NSURL!
    
    这会强制展开
    info[UIImagePickerControllerMediaURL]
    (这很糟糕,因为如果它是
    nil
    ,应用程序将崩溃),并将其强制转换为隐式展开的可选
    NSURL。那没有道理。只需执行条件展开(并展开为
    NSURL
    ,而不是
    NSURL!
    ):

  • 下一行调用
    filePathURL

    var videoFileURL = videoDataURL.filePathURL
    
    如果您想要一个文件URL,那么您已经有了一个,因此不需要转换,只需使用
    videoDataURL
    。如果您确实想要一条路径,您可以使用
    path
    方法:

    let videoPath = videoDataURL.path
    
    坦率地说,苹果正试图让我们不再使用字符串路径,所以只需使用原始的
    videoDataURL
    ,避免同时使用
    path
    filePathURL

  • 您正在使用带有MappedFile内容的
    数据

    var video = NSData.dataWithContentsOfMappedFile("\(videoDataURL)")
    
    如果您真的想将
    数据与MappedFile的内容一起使用,正确的Swift语法是:

    let video = NSData(contentsOfMappedFile: videoPath!)
    
    但是
    dataWithContentsOfMappedFile
    已弃用,因此您应该改用:

    let video = try NSData(contentsOfFile: videoPath!, options: .DataReadingMappedIfSafe)
    
    或者,完全绕过
    视频路径
    ,您可以:

    let video3 = try NSData(contentsOfURL: videoDataURL, options: .DataReadingMappedIfSafe)
    
    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)
        }
    }
    
    显然,那些
    try
    格式副本应该在带有
    catch
    块的
    do
    块中完成

  • 顺便说一句,正如您将在我上面的所有示例中看到的,在可能的情况下,应该使用
    let

  • --

    坦率地说,我建议不要将其加载到
    NSData
    中。只需使用
    NSFileManager
    复制它,这样可以更有效地使用内存。如果视频很长,它可能相当大,您应该避免在任何给定的时间点将整个视频加载到内存中

    所以你可以:

    let video3 = try NSData(contentsOfURL: videoDataURL, options: .DataReadingMappedIfSafe)
    
    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
    。此请求的构造是一个单独的问题,但希望您能理解:对于照片或视频等大型资产,如果可以避免,请不要使用资产实例化
    NSData

    在选择视频后,此方法将被调用

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true, completion: nil)
        print("in here")
        if let pickedVideo = info[UIImagePickerController.InfoKey(rawValue: UIImagePickerController.InfoKey.mediaURL.rawValue)] as? URL {
                print(pickedVideo)
            do {
                print("Converted")
               // let VideoData = try Data(contentsOf: pickedVideo)
                uploadVideo(VideoData: try Data(contentsOf: pickedVideo), URL: pickedVideo)
                
            } catch let error {
                print(error.localizedDescription)
            }
            
            }
       
    }
    

    请澄清你的问题。您发布的代码中的“info”参数有什么问题?冷却发布的代码在Swift中工作而不是swift2我询问它在Swift 2中如何工作此我的函数参数在其中没有信息“func imagePickerController(picker:UIImagePickerController,didFinishPickingImage:UIImage,editingInfo:[字符串:AnyObject]?)发布的代码在Swift 2中以何种方式不起作用?注释中的委托方法已弃用。用你问题中的那个。只需将
    info
    参数修改为
    [String:AnyObject]
    。谢谢,我搞错了。您还应该解释一下这个答案是如何解决问题的。@rmaddy-我正在解决这个棘手的问题,但我已经修改了答案来描述问题。嗨,Rob!是否有任何方法可以读取范围内的数据并上传到服务器。示例:假设我有一个1GB的视频,所以我先读取0-50MB并上传到服务器,然后读取50-100MB并上传,依此类推。@Farookueazam-因为您仍在处理大量上传(每个50MB),我倾向于为每个50MB块创建单独的文件。例如,创建
    InputStream
    并开始读取内容(可能每次读取10-100kb),写入为每个50MB块创建的
    OutputStream
    。然后您可以对这些单独的文件进行基于文件的上传(非常适合后台
    URLSession
    )。但这超出了这个问题的范围,所以如果您真的有其他问题,请在堆栈溢出上创建您自己的问题。