File name that saved in document directory have space character - ios

I want to download video file and save it in the document directory but when i try show that downloaded video, i can't create URL of that file.
i'm using this code for create path for save file. my file name have spacing : (mobileslider video.mp4), and i want to save this video with own name but i can't create url path that contain space. how can solve this problem?
if let url = URL(string:videoURL){
showVideoFromNib(nibURL:url)
}
when i try to remove space from videoURL, showVideoFromNib method called but don't show the video. and when use orginal url, showVideoFromNib method didn't call.
Edit 1:
i change destination path from :
let destination = DownloadRequest.suggestedDownloadDestination(for: .documentDirectory)
to :
let destination: DownloadRequest.DownloadFileDestination = { _, _ in
let pathComponent = "pack\(self.packID)-\(selectRow + 1).mp4"
let directoryURL: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let folderPath: URL = directoryURL.appendingPathComponent("Downloads", isDirectory: true)
let fileURL: URL = folderPath.appendingPathComponent(pathComponent)
return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}
now i can create URL and my show video method call but video don't show.
this is my new sample path:
/Users/MyUser/Library/Developer/CoreSimulator/Devices/2C2B6A39-5426-4E2C-B25A-CF64817AF26F/data/Containers/Data/Application/5A1BB109-D452-4F03-8820-EE1120E07C3D/Documents/Downloads/pack7-2.mp4
this file exist in this path but video player don't show this.

I solve problem. i'm using
let path = destinationUrl.absoluteString
instead of
let path = destinationUrl.path

Related

URLResourceValues not working for renaming a file

I have to rename some files in a directory in the Documents directory. I'm trying with URLResourceValues:
let fileURLs = try! FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil)
fileURLS.forEach { fileURL in
// calculate newFileName
var resourceValues = URLResourceValues()
resourceValues.name = newFilename
var mutableFileURL = fileURL
try! mutableFileURL.setResourceValues(resourceValues)
}
After setting resourceValues.name I see this in the console...
key NSMutableString "NSURLNameKey" 0x00000001e7a8a368
value NSString "newName.jpg" 0x0000000283f61fe0
So that part is working. The try! completes without crashing so there were no errors thrown. But mutableFileURL is unchanged. It's got the old name, not the new name.
I see in the docs that setting read-only properties or setting properties not supported will be ignored and will not throw an error. But in my research I see this approach used commonly for renaming files. And I don't think it's a write access thing because if I use the old way it works fine:
try! FileManager.default.moveItem(at: fileURL, to: newFileURL)
What could I be missing here?
P.S. app targets iOS 14, running on a real device running iOS 16.1
You have not shown how you know things didn't work. But you say:
But mutableFileURL is unchanged
Your code isn't supposed to change mutableFileURL. If you're looking at mutableFileURL to see what happened, that's the problem.
The URL here is just a pointer to the file on disk. That's the whole point of the setResourceValues approach. Your code changes the name of the file on disk (and mutableFileURL, the pointer, is now invalid and should just be thrown away).
If you re-fetch the contents of the documents directory, you'll see that your code worked just fine.
Complete example, showing both what I think you are doing and how to do this correctly:
// --- create the file ---
let fm = FileManager.default
let docsurl = try fm.url(
for: .documentDirectory, in: .userDomainMask,
appropriateFor: nil, create: false
)
let newurl = docsurl.appending(path: "howdy.txt")
try "howdy".write(to: newurl, atomically: true, encoding: .utf8)
let arr = try fm.contentsOfDirectory(
at: docsurl, includingPropertiesForKeys: nil
)
arr.forEach { print($0.lastPathComponent) }
// howdy.txt
// --- rename the file ---
var values = URLResourceValues()
values.name = "hello.txt"
var mutableurl = newurl
try mutableurl.setResourceValues(values)
// --- how did we do? this is _not_ the way:
print(mutableurl)
// file:///.../Documents/howdy.txt
// --- how did we do? this _is_ the way
let arr2 = try fm.contentsOfDirectory(
at: docsurl, includingPropertiesForKeys: nil
)
arr2.forEach { print($0.lastPathComponent) }
// hello.txt

Issue getting URL from String for use with AVPlayer

I have constructed a string that is the directory path and file name of file i would like to play in AVPlayer. But I'm struggling to convert this to a URL.
let dataPath = ("\(packDirectory)/").appending((cachedFilePath as NSString).lastPathComponent)
print(dataPath)
audioFileURL = dataPath
self.audioPlayerItem = AVPlayerItem(url: NSURL.fileURL(withPath: audioFileURL) as URL)
print(self.audioPlayerItem)
print(dataPath) returns:
/Users/Geoff/Library/Developer/CoreSimulator/Devices/A31BF8F8-21F6-4227-97B6-9DBDED26CA3E/data/Containers/Data/Application/788085B9-242E-46E7-9644-6A3BF9D515DB/Documents/Next-pk000/7b54d8a0f1a64b710058d4408ca4d696_The%20Name%20of%20the%20Wind%2029-92.mp3
print(self.audioPlayerItem) returns: - the url part:
URL = file:///Users/Geoff/Library/Developer/CoreSimulator/Devices/A31BF8F8-21F6-4227-97B6-9DBDED26CA3E/data/Containers/Data/Application/788085B9-242E-46E7-9644-6A3BF9D515DB/Documents/Next-pk000/7b54d8a0f1a64b710058d4408ca4d696_The%2520Name%2520of%2520the%2520Wind%252029-92.mp3
I don't really understand this stuff but i can see 2 issues with this.
1) file:// : i have purposely removed this from my "dataPath" as when using file manager it cant find anything with this prefix. i have used this code for that:
userDirectory.removeSubrange(userDirectory.startIndex..<userDirectory.index(userDirectory.startIndex, offsetBy: 7))
let packDirectory = userDirectory.appending("Next-\(self.selectedPack!)")
2) the encoding in the .lastComponent has been changed from %20 to %2520
Very confused !
---- EDIT ----
let urlItem = AVPlayerItem(url: URL(fileURLWithPath: audioFileURL))
if let urlAsset = urlItem.asset as? AVURLAsset {
self.audioPlayerItem = AVPlayerItem(url: NSURL(string: urlAsset.url.path) as! URL)
print(urlAsset.url.path)
}
print(self.audioPlayerItem!)
print(urlAsset.url.path) returns :
/Users/Geoff/Library/Developer/CoreSimulator/Devices/A31BF8F8-21F6-4227-97B6-9DBDED26CA3E/data/Containers/Data/Application/BAD0194A-8CDD-44CE-BF99-B9FF35E23BCA/Documents/Next-pk000/7b54d8a0f1a64b710058d4408ca4d696_The%20Name%20of%20the%20Wind%2029-92.mp3
print(self.audioPlayerItem!) returns:
<AVPlayerItem: 0x7bf81b60, asset = <AVURLAsset: 0x7bf87c70, URL = /Users/Geoff/Library/Developer/CoreSimulator/Devices/A31BF8F8-21F6-4227-97B6-9DBDED26CA3E/data/Containers/Data/Applicati ... 9-92.mp3>>
self.audioPlayerItem = AVPlayerItem(url: URL(fileURLWithPath: urlAsset.url.path))
prints:
file:///Users/Geoff/Library/Developer/CoreSimulator/Devices/A31BF8F8-21F6-4227-97B6-9DBDED26CA3E/data/Containers/Data/Application/7C212656-8E1C-44C8-9951-4444FB5EF853/Documents/Next-pk000/7b54d8a0f1a64b710058d4408ca4d696_The%2520Name%2520of%2520the%2520Wind%252029-92.mp3
even using something like:
let asset = AVAsset(url: URL(string: urlAsset.url.path)!) as AVAsset
results in losing some of the url:
<AVPlayerItem: 0x79716ed0, asset = <AVURLAsset: 0x797185d0, URL = /Users/Geoff/Library/Developer/CoreSimulator/Devices/A31BF8F8-21F6-4227-97B6-9DBDED26CA3E/data/Containers/Data/Applicati ... 9-92.mp3>>
And nothing plays. So basically i think it won't play with the file:// prefix but when i plug in the string without it something cuts the path at the i in applications???
You can read about absoluteString and path of URL documentation.
For getting self.audioPlayerItem's URL with lacking of file:/// you can access asset of self.audioPlayerItem and get path of asset.url
let asset = self.audioPlayerItem?.currentItem?.asset
if asset == nil {
return nil
}
if let urlAsset = asset as? AVURLAsset {
return urlAsset.url.path
}
Edited: if you use local file, init URL with URL.init(fileURLWithPath: ) instead of URL.init(string: ). If you use URL.init(string: ), string will be full path (contains file:///), not path.
That's ok, the decoding result is the same. Try to read reference A html space is showing as %2520 instead of %20
P/S: that snippet is just pseudo, please follow the idea from that snippet.

How to resolve: FileManager.fileExists returns incorrect false [duplicate]

How is it possible?
let exists = NSFileManager.defaultManager().fileExistsAtPath(path.absoluteString)
print("exists: \(exists)") //false
This is path.absoluteString
//file:///Users/kuna/Library/Developer/CoreSimulator/Devices/92BD140D-5C14-43C4-80D6-904BB9594ED6/data/Containers/Data/Application/5B818832-BB19-4047-A7F8-1487F36868D6/Documents/wishlists/68/147/128/IMG_0006.PNG
And you can see it is there where it should be:
What is going on?
(The code in this answer has been updated for Swift 3 and later.)
Apparently your path variable is a NSURL (describing a file path). To get the path as
a string, use the path property, not absoluteString:
let exists = FileManager.default.fileExists(atPath: path.path)
absoluteString returns the URL in a string format, including
the file: scheme etc.
Example:
let url = URL(fileURLWithPath: "/path/to/foo.txt")
// This is what you did:
print(url.absoluteString)
// Output: file:///path/to/foo.txt
// This is what you want:
print(url.path)
// Output: /path/to/foo.txt
If you want to check if a path exist,you should check path
let url = NSURL(string: "balabala")
let path = url?.path
//Check path

FileManager fileExists() always returns false (iOS 10, swift 3) [duplicate]

How is it possible?
let exists = NSFileManager.defaultManager().fileExistsAtPath(path.absoluteString)
print("exists: \(exists)") //false
This is path.absoluteString
//file:///Users/kuna/Library/Developer/CoreSimulator/Devices/92BD140D-5C14-43C4-80D6-904BB9594ED6/data/Containers/Data/Application/5B818832-BB19-4047-A7F8-1487F36868D6/Documents/wishlists/68/147/128/IMG_0006.PNG
And you can see it is there where it should be:
What is going on?
(The code in this answer has been updated for Swift 3 and later.)
Apparently your path variable is a NSURL (describing a file path). To get the path as
a string, use the path property, not absoluteString:
let exists = FileManager.default.fileExists(atPath: path.path)
absoluteString returns the URL in a string format, including
the file: scheme etc.
Example:
let url = URL(fileURLWithPath: "/path/to/foo.txt")
// This is what you did:
print(url.absoluteString)
// Output: file:///path/to/foo.txt
// This is what you want:
print(url.path)
// Output: /path/to/foo.txt
If you want to check if a path exist,you should check path
let url = NSURL(string: "balabala")
let path = url?.path
//Check path

AVAsset has 0 tracks even though video exists and plays fine from the Camera Roll: troubleshooting steps?

Our app lets users record and save videos to their Camera Roll. However, we can't seem to play back the videos in an AVPlayer even though the saved videos play back fine from the Camera Roll.
For some reason, a valid video file reports back as having 0 tracks.
Code:
func playPreview(videoUrl: NSURL) {
let asset = AVAsset.assetWithURL(videoUrl) as? AVAsset
println("\(asset!.tracks.count) tracks found for \(videoUrl)")
let playerItem = AVPlayerItem(asset: asset)
player = AVPlayer(playerItem: playerItem)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = CGRectMake(0, 0, 320, 320)
view.layer.addSublayer(playerLayer)
player.seekToTime(kCMTimeZero)
player.play()
}
The videoUrl we're testing is:
file:///var/mobile/Containers/Data/Application/F532DF34-371C-437E-A121-04C532349720/Documents/editedVideo-7325.mp4
The file exists and is 419498 bytes large as you can see from the code and output below.
Given that the file clearly has content, why are the tracks reporting back as 0? Besides checking the number of tracks, what else can we do to troubleshoot?
func listFiles() {
let allPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let docsPath = allPaths[0] as! NSString
if let files = NSFileManager.defaultManager().contentsOfDirectoryAtPath(docsPath as String, error: nil) as? [String] {
println("Found \(files.count) file(s) in \(docsPath):")
for filename in files {
let filePath = docsPath.stringByAppendingFormat("/\(filename)") as String
var attr = NSFileManager.defaultManager().attributesOfItemAtPath(filePath, error: nil)
if let _attr:NSDictionary = attr {
let fileSize = _attr.fileSize()
println("\(filename) # \(fileSize) bytes")
}
}
}
}
Found 11 file(s) in /var/mobile/Containers/Data/Application/5809B294-8A54-4506-A79A-F19E7C877A4A/Documents:
editedVideo-2252.mp4 # 732567 bytes
editedVideo-3582.mp4 # 728485 bytes
editedVideo-5175.mp4 # 413897 bytes
editedVideo-5366.mp4 # 607992 bytes
editedVideo-5459.mp4 # 350652 bytes
editedVideo-622.mp4 # 763026 bytes
**editedVideo-7325.mp4 # 419498 bytes**
editedVideo-7428.mp4 # 858742 bytes
editedVideo-7948.mp4 # 923791 bytes
editedVideo-8612.mp4 # 429463 bytes
editedVideo-9363.mp4 # 511307 bytes
The videoUrl parameter did not point to the right file.
Use this approach when referencing videos locally:
let filename = "yourvideo.mp4"
let allDirs = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDir = allDirs[0] as! NSString
let filePath = documentsDir.stringByAppendingPathComponent(filename)
let fileUrl = NSURL(fileURLWithPath: filePath)
The Documents directory path (e.g., /var/mobile/Containers/Data/Application/8BA180AB-2DD9-4FD8-9312-2BF006914561/Documents/) apparently changes.
You can't expect the same path every time and therefore can't use a fully formed file URL string like we were, even for testing purposes.
The parent directory to the Documents directory -- the alphanumeric string -- is what changes.
The NSURL can mean two different things :
The absolute file path that you mentioned i.e. starting with file://
The URL that you get from ALAsset. You can get it using :
NSURL *asseturl = [asset valueForProperty:ALAssetPropertyAssetURL];
where "asset" is of type ALAsset
This URL can then be used to get AVAsset using :
AVAsset.assetWithURL
Please try the second method.

Resources