I'd like to know how could I create a URL from a path String.
Here my code:
let completePath = "/Volumes/MyNetworkFolder/"
do {
let items = try FileManager.default.contentsOfDirectory(atPath: completePath)
for item in items {
if item.hasDirectoryPath { //String has no member hasDirectoryPath
itemList.append(item)
}
}
} catch {
print("Failed to read dir")
let buttonPushed = dialogOKCancel(question: "Failed to read dir", text: "Map the network folder")
if(buttonPushed) {
exit(0)
}
}
I'd like to add only folders to the itemList array. The hasDirectoryPath is an URL method.
How could i change my code to get URLs not String.
Thank you in advance for any help you can provide.
Better use the contentsOfDirectory(at url: URL, ...) method of
FileManager, that gives you an array of URLs instead of
strings:
let dirPath = "/Volumes/MyNetworkFolder/"
let dirURL = URL(fileURLWithPath: dirPath)
do {
let items = try FileManager.default.contentsOfDirectory(at: dirURL,
includingPropertiesForKeys: nil)
for item in items {
if item.hasDirectoryPath {
// item is a URL
// item.path is its file path as a String
// ...
}
}
} catch {
print("Failed to read dir:", error.localizedDescription)
}
Related
Currently, I can fetch the download url by file name via firebase storage reference.
I would like to retrieve all download URLS in a specific child without using a file name and only using the last child name.
Simply adding every download url in a list/array
How can I accomplish this with my given reference.
func getDownloadURL() {
let ref = Storage.storage().reference()
let fileName = "Lessons_Lesson1_Class1.mp3"
let starsRef = ref.child("Daily Meditations").child("Lessons").child("Lesson 1").child(fileName)
// Fetch the download URL
starsRef.downloadURL { url, error in
if let error = error {
// Handle any errors
print(error)
} else {
// Get the download URL for 'Lessons_Lesson1_Class1.mp3'
print(url)
}
}
}
Firebase Refrence Docs
let stg = Storage.storage().reference()
let path = "Daily Meditations/Lessons/Lesson 1"
stg.child(path).listAll { (list, error) in
if let error = error {
print(error)
} else {
let inStorage = list.items.map({ $0.name })
print(inStorage) // an array of file names in string format
}
}
I assume spaces are allowed in path names since you're using them. To list all of the files in a path, use listAll. The method will return a StorageListResult object which I've named list.
https://firebase.google.com/docs/reference/swift/firebasestorage/api/reference/Classes/StorageListResult
So I was able to combine List all files and Download URL to achieve what I was trying to accomplish from the firebase documentation.
Here is the code:
func getDownloadURl() {
let ref = Storage.storage().reference()
let storageReference = ref.child("Lessons/Lesson 1")
storageReference.listAll { (result, error) in
if let error = error {
print(error)
}
for item in result.items {
//List storage reference
let storageLocation = String(describing: item)
let gsReference = Storage.storage().reference(forURL: storageLocation)
// Fetch the download URL
gsReference.downloadURL { url, error in
if let error = error {
// Handle any errors
print(error)
} else {
// Get the download URL for each item storage location
print(url!)
}
}
}
}
}
If anyone is using with VUE 2.6 and TS, here is my workaround
Imports
import {
getStorage,
ref,
getDownloadURL,
listAll,
StorageReference,
} from "firebase/storage";
async mounted(): Promise<void> {
const storage = getStorage();
const imageRefs = await listAll(ref(storage, "SOME BUCKET"))
.then((refs) => {
return refs.items;
})
.catch((error) => {
// Handle any errors
});
(imageRefs as StorageReference[]).forEach((item) => {
console.log(item);
getDownloadURL(item).then((downloadURL) => {
console.log(downloadURL);
this.model.listFiles.push(downloadURL);
});
});
console.log(imageRefs);
console.log(this.model.listFiles);
},
I'm trying to download a file with SwiftyDropbox but I have problemas with the path. I have a file in mi Dropbox "prueba.txt":
Dropbox file
And this is the code that I use to download in my app.
import UIKit
import SwiftyDropbox
let clientDB = DropboxClientsManager.authorizedClient
class Controller: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
DropboxClientsManager.authorizeFromController(UIApplication.shared, controller: self, openURL: {
(url: URL) -> Void in UIApplication.shared.open(url)
})
let fileManager = FileManager.default
let directoryURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let destURL = directoryURL.appendingPathComponent("/test.txt")
let destination: (URL, HTTPURLResponse) -> URL = { temporaryURL, response in
return destURL
}
clientDB?.files.download(path: "/prueba.txt", overwrite: true, destination: destination)
.response{ response, error in
if response != nil{
self.cargarDatosCliente()
//print (response)
} else if let error = error{
print (error)
}
}
.progress{ progressData in
print(progressData)
}
}
}
I try different ways but always obtain the same problem with "path", always the error is path/not_found/...
I try with other path but is the same problem.
Could you help me? Where is my mistake?
Thanks!
The problem is that "/prueba.txt" is a local file path. Dropbox expects you to give it a file path for their remote server.
You can retrieve those by using listFolder and listFolderContinue.
For example, if you want to retrieve the file paths in the root folder of your app or dropbox use:
var path = ""
clientDB?.files.listFolder(path: path).response(completionHandler: { response, error in
if let response = response {
let fileMetadata = response.entries
if response.hasMore {
// Store results found so far
// If there are more entries, you can use `listFolderContinue` to retrieve the rest.
} else {
// You have all information. You can use it to download files.
}
} else if let error = error {
// Handle errors
}
})
The fileMetadata contains the path you need. For example, you can get the path to the first file like this:
let path = fileMetadata[0].pathDisplay
If you're getting metadata about files from the API, this would be the "pathLower" property of a FileMetadata object.
client?.files.download(path: fileMetadata.pathLower!, overwrite: true, destination: destination)
.response { response, error in
if let response = response {
print(response)
} else if let error = error {
print(error)
}
}
I am very new to learning to code in Swift. I am trying to make an application that keeps a list of people who are coming in. I want it to log the name they input, time of visit, and the nature of their visit. However, I want this to be able to be exported to a program like Numbers or Excel. I have found some info on storing the inputs from the user but those seem to get deleted if the app is closed. I can't seem to find any other info, but perhaps I'm just searching the wrong info. Any help or guidance is appreciated.
Just store your log in a Array and then with this function you safe it to a .csv file.
func saveCSV(_ name : String,_ customUrl : URL) -> Bool {
let fileName = "\(name).csv"
let b = customUrl.appendingPathComponent(fileName)
var csvText = ""
var id = "1"
var name = "test"
csvText = "ID,Name\n"
let newLine = "\(id),\(name))\n"
csvText.append(newLine)
//or create a loop
// Task is my custom Struct
var array : [Task]
for task in customArray {
let newLine = "\(task.ean),\(task.menge),\(task.name)\n"
csvText.append(newLine)
}
do {
try csvText.write(to: b, atomically: true, encoding: String.Encoding.utf8)
return true
} catch {
print("Failed to create file")
print("\(error)")
return false
}
}
func createDic()->URL?{
let documentsPath1 = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
// CSV is the folder name
let logsPath = documentsPath1.appendingPathComponent("CSV")
do {
try FileManager.default.createDirectory(atPath: logsPath!.path, withIntermediateDirectories: true, attributes: nil)
return logsPath
} catch let error as NSError {
NSLog("Unable to create directory \(error.debugDescription)")
}
return nil
}
var customUrl = createDic()
and now you can call it :
if saveCSV(userList, customUrl){
print("success")
}
and after this you can do what you want with the .csv file
I try to create an OutputStream to an app group folder, which is created as follows:
func createProjectDirectoryPath(path:String) -> String
{
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.xyz")
let logsPath = containerURL!.appendingPathComponent(path)
NSLog("12345- folder path: %#", logsPath.path)
do {
try FileManager.default.createDirectory(atPath: logsPath.path, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
NSLog("12345- Unable to create directory %#", error.debugDescription)
}
return logsPath.path
}
This function gives me a path like this
/private/var/mobile/Containers/Shared/AppGroup/40215F20-4713-4E23-87EF-1E21CCFB45DF/pcapFiles
This folder exists, because the line FileManager.default.fileExists(path) returns true. The next step is to append a generated filename to the path, which I am doing here
let urlToFile = URL(string: createProjectDirectoryPath(path: "pcapFiles").appending("/\(filename)"))
which gives me the correct new path
/private/var/mobile/Containers/Shared/AppGroup/40215F20-4713-4E23-87EF-1E21CCFB45DF/pcapFiles/39CC2DB4-A6D9-412E-BAAF-2FAA4AD70B22.pcap
If I call this line, ostream is always nil
let ostream = OutputStream(url: urlToFile!, append: false)
Do I miss something? The OutputStream should create the file on this path, but for unknown reason, it is not possible.
PS: AppGroup is enabled in Capabilities and in developers console.
Your createProjectDirectoryPath() function returns a file path,
therefore you must use URL(fileURLWithPath:) to convert that to an
URL. Alternatively, modify your function to return an URL instead:
func createProjectDirectoryPath(path:String) -> URL? {
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.xyz")
let logsURL = containerURL!.appendingPathComponent(path)
do {
try FileManager.default.createDirectory(at: logsURL, withIntermediateDirectories: true)
} catch let error as NSError {
NSLog("Unable to create directory %#", error.debugDescription)
return nil
}
return logsURL
}
In addition, you have to call open() on all Stream objects before
they can be used, this will also create the file if it did not exist
before:
guard let logsURL = createProjectDirectoryPath(path: "pcapFiles") else {
fatalError("Cannot create directory")
}
let urlToFile = logsURL.appendingPathComponent(filename)
guard let ostream = OutputStream(url: urlToFile, append: false) else {
fatalError("Cannot open file")
}
ostream.open()
I have this function to save an image inside the tmp folder
private func saveImageToTempFolder(image: UIImage, withName name: String) {
if let data = UIImageJPEGRepresentation(image, 1) {
let tempDirectoryURL = NSURL.fileURLWithPath(NSTemporaryDirectory(), isDirectory: true)
let targetURL = tempDirectoryURL.URLByAppendingPathComponent("\(name).jpg").absoluteString
print("target: \(targetURL)")
data.writeToFile(targetURL, atomically: true)
}
}
But when I open the temp folder of my app, it is empty. What am I doing wrong to save the image inside the temp folder?
absoluteString is not the correct method to get a file path of
an NSURL, use path instead:
let targetPath = tempDirectoryURL.URLByAppendingPathComponent("\(name).jpg").path!
data.writeToFile(targetPath, atomically: true)
Or better, work with URLs only:
let targetURL = tempDirectoryURL.URLByAppendingPathComponent("\(name).jpg")
data.writeToURL(targetURL, atomically: true)
Even better, use writeToURL(url: options) throws
and check for success or failure:
do {
try data.writeToURL(targetURL, options: [])
} catch let error as NSError {
print("Could not write file", error.localizedDescription)
}
Swift 3/4 update:
let targetURL = tempDirectoryURL.appendingPathComponent("\(name).jpg")
do {
try data.write(to: targetURL)
} catch {
print("Could not write file", error.localizedDescription)
}
A solution is to try to write directly to the complete FileManager() file path like so :
let filePath = FileManager.default.temporaryDirectory.appendingPathComponent("\(id).mp4")
//You can choose a specific directory with FileManager.default.urls(for:in:)
before doing
DispatchQueue.main.async {
do {
try data?.write(to: filePath)
//Write is a success
} catch {
print(error.localizedDescription)
//Error while trying to write
}
}