How do I convert an assets URL into filesystem URL? - ios

TLDR; how to convert NSURL of form "assets-library://...." to "file:///...."
In this scenario, the user takes a video in app and saves it to their images with the ALAssetsLibrary method (writeVideoAtPathToSavedPhotosAlbum). From this method upon competion, I get an assetURL in the form "assets-library://asset/asset.mov?id=F60213D1-3C39-44A8-8D21-80587D1CF843&ext=mov".
I need to convert this asset URL to a file system url with format file:///... so that I can upload the file. (fileuploader requires file system NSURL of asset)
I've tried doing this to convert the asset URL into a filesystem URL but it doesn't work
writeVideoAtPathToSavedPhotosAlbum(outputURL, completionBlock: { (assetURL:NSURL!, error:NSError!) }
......
let pathDocumentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let filePath = "\(pathDocumentDirectory)/\(assetURL.lastPathComponent!)"
let fileUrl = NSURL(fileURLWithPath: filePath)
Any ideas?

Related

User's document directory returning nil with FileManager

I'm trying to write a file locally but no success. When I try to get the user's document directory it returns nil and I believe this is why my file is not been stored.
Also, I have many doubts of what the "user's document directory" is supposed to mean. Is it the "Documents/" inside "iCloud Drive" or "on my phone". Should I be looking in another place instead of "Files" app? I'm using the iPhone simulator.
My code is designed as follow. documentFolderURL, fileURL and url are all nil when debugging.
let documentFolderURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last
let ext: String = type ?? "pdf"
let name = "extrato." + ext
let fileURL = documentFolderURL?.appendingPathComponent(name)
do {
if let url = fileURL {
try file.write(to: url, options: .atomic)
}
} catch {...}
Use the throwing API to get an error (there should be none)
do {
let documentFolderURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let ext: String = type ?? "pdf"
let fileURL = documentFolderURL.appendingPathComponent(name).appendingPathExtension(ext)
try file.write(to: fileURL, options: .atomic)
} catch { print(error) }
It seems that you are creating the file successfully, but you aren't looking for it in the right place.
You can navigate to the simulator's User Defaults folder by:
Print the file path of the simulator's documents directory. print(documentFolderURL) should print something like file:///Users/yourname/Library/Developer/CoreSimulator/Devices/8DAF542C-4B37-41D1-BA43-1D7C2A32E585/data/Containers/Data/Application/63545C94-56F5-3B11-B601-543801BE717A/Documents/
Copy the entire url EXCEPT the leading file:// (in other words, start with /User/yourname...
Open your macbook's Finder app, and press command + shift + g. This will allow you to...(drum roll please)...
Paste in the url to navigate to your simulator's documents directory.
Your file should be there :)

iOS / Swift failing to write file as treating file path as directory path [duplicate]

This question already has an answer here:
UIImage(contentsOfFile:) returning nil despite file existing in caches directory [duplicate]
(1 answer)
Closed 4 years ago.
I have the following swift function that I hoped would save incoming bytes to a JPEG file on iOS. Unfortunately an exception is thrown by the call to data.write and I get the error message
The folder “studioframe0.jpg” doesn’t exist. writing to file:/var/mobile/Containers/Data/Application/2A504F84-E8B7-42F8-B8C3-3D0A53C1E11A/Documents/studioframe0.jpg -- file:///
Why does iOS think it is a directory path to a directory which does not exist as opposed to a file that I am asking it to write?
func saveToFile(data: Data){
if savedImageCount < 10 {
guard let documentDirectoryPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
return
}
let imgPath = URL(fileURLWithPath: documentDirectoryPath.appendingPathComponent("studioframe\(savedImageCount).jpg").absoluteString)
savedImageCount += 1
do {
try data.write(to: imgPath, options: .atomic)
print("Saved \(imgPath) to disk")
} catch let error {
print("\(error.localizedDescription) writing to \(imgPath)")
}
}
}
URL(fileURLWithPath together with absoluteString is wrong.
You would have to write (note the different URL initializer):
let imgPath = URL(string: documentDirectoryPath.appendingPathComponent("studioframe\(savedImageCount).jpg").absoluteString)
but this (URL → String → URL) is very cumbersome, there is a much simpler solution, please consider the difference between (string) path and URL
let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! // the Documents directory is guaranteed to exist.
let imgURL = documentDirectoryURL.appendingPathComponent("studioframe\(savedImageCount).jpg")
...
try data.write(to: imgURL, options: .atomic)

Use an URL as a name to save a file

I download a json file with this code
URLSession.shared.dataTask(with: NSURL(string: url)! as URL, completionHandler: { (data, response, error) -> Void in
if let this = weakSelf{
and then I try to save it locally
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent(url)
print(fileURL)
try data?.write(to: fileURL)
} catch {
print(error)
}
I want to use the url of the JSON file as its name when I try to save it. But I get an error tellig me that the path dose not exist... Every think works file it I try to save it with a normal name. Do you have an idea on how to solve that?
It’s a bad idea to use the url as a file name. You would probably want to process the url first, like remove scheme and slashes
You cannot use an entire URL as file name because the URL (string) contains slashes and slashes are path separators in the file system.
You can use
url.lastPathComponent
to get the file name of the URL. And don't use NSURL in Swift 3. There is a native URL struct.

loading data object from local file in Swift 3

I'm struggling to get an image file loaded in Swift 3.
Here is the code:
do {
let imageData = try Data(contentsOf: imageUrl2.asURL())
} catch {
print ("loading image file error")
}
And the current Url String is:
file:///Users/veikoherne/Library/Developer/CoreSimulator/Devices/889A08D5-B8CC-458C-99FF-643A4BA1A806/data/Containers/Data/Application/F64ED326-7894-4EE7-AA3B-B1BB10DF8259/Documents/img2017-03-23 17:39:24.jpg
and obviously I have checked that this file exists and is valid image. It always ends up telling me "loading image file error". Anyone have experiences loading local data in Swift 3?
The answer mentioned was using NSData object and probably Swift 2. Current Swift 3 refuses to bridge NSData to Data, that's why I have to use Data.
Loading data from local file you should use "contentsOfFile:" method.
Reference link: https://www.hackingwithswift.com/example-code/strings/how-to-load-a-string-from-a-file-in-your-bundle
So in case of reading data you can use:
Data(contentsOf: <URL>, options: <Data.ReadingOptions>)
Reading a plain text as a String, use:
String(contentsOfFile: <LocalFileDirPath>)
Reading an image from document directory, use:
UIImage(contentsOfFile: <LocalFileDirPath>)
Hope this would be helpful!
I experienced the same issue when trying to retrieve a file that I just downloaded. If you have saved a file from some url like I did, this should work:
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
let localUrl = documentDirectory.appendingPathComponent("somefile.txt")
if FileManager.default.fileExists(atPath: localUrl.path){
if let cert = NSData(contentsOfFile: localUrl.path) {
return cert as Data
}
}
Swift 5 version.
func loadFileFromLocalPath(_ localFilePath: String) ->Data? {
return try? Data(contentsOf: URL(fileURLWithPath: localFilePath))
}

How to save NSData as gif to Album

I use function here https://gist.github.com/westerlund/eae8ec71cdac88be7c3a
to create a gif file of an array of images, but the return type is NSData.
How can I use this data and save it to album?
I have tried UIImageWriteToSavedPhotosAlbum. It's not work, it only saved the first image of the image array. I have googled a function named writeimagedatatosavedphotosalbum, but it's already been deprecated in iOS9.
So what's the latest way the save a .gif file to album?
First Get a file URL
guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let fileURL = documentsDirectory.appendingPathComponent("myGifFile.gif")
Write gifData to File URL
try? gifData.write(to: fileURL)
Save the file from URL to Album
PHPhotoLibrary.shared().performChanges ({
PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: fileURL)
}) { saved, error in
if saved {
print("Your image was successfully saved")
}
}

Resources