Ios 如何将视频(在多媒体资料中)转换为NSData?迅速地
我只是在Swift imagePickerController中没有“信息”,所以我不知道如何获取url并将其转换为数据发送到web服务Ios 如何将视频(在多媒体资料中)转换为NSData?迅速地,ios,swift,swift3,Ios,Swift,Swift3,我只是在Swift imagePickerController中没有“信息”,所以我不知道如何获取url并将其转换为数据发送到web服务 func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) { var videoDataURL = info[UIImagePickerControllerMediaURL]
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
数据
:
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
)。但这超出了这个问题的范围,所以如果您真的有其他问题,请在堆栈溢出上创建您自己的问题。