Using IOS 9.1, running on Xcode 7.1.1. under El Capitan. I am trying out the tutorial on accessing dropbox thru their (new maybe) SwiftDropbox library by following this page.
https://blogs.dropbox.com/developers/2015/05/try-out-swiftydropbox-the-new-swift-sdk-for-dropbox-api-v2/
Started well, managed to connect and get authorised, but unable to do much more cause the code posted to their tutorial doesn't compile.
if let client = Dropbox.authorizedClient {
// Get the current user's account info
client.usersGetCurrentAccount().response { response, error in
if let account = response {
println("Hello \(account.name.givenName)")
} else {
println(error!)
}
}
// List folder
client.filesListFolder(path: "").response { response, error in
if let result = response {
println("Folder contents:")
for entry in result.entries {
println(entry.name)
}
} else {
println(error!)
}
}
Complaining that DropboxClient has no member "usersGetCurrentAccount" or "filesListFolder" which I assume are some sort method calls {pretty new to swift too}. Can not seem to google any useful leads on this? What should this code read/say?
Bon,
THANKYOU smarx; you put me on the right path. Here is the final code; with two minor fixes to the tutorial he mentioned here.
// ViewController.swift
import UIKit
import SwiftyDropbox
class ViewController: UIViewController {
#IBAction func linkButtonPressed(sender: AnyObject) {
if (Dropbox.authorizedClient == nil) {
Dropbox.authorizeFromController(self)
} else {
print("User is already authorized!")
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Verify user is logged into Dropbox
if let client = Dropbox.authorizedClient {
// Get the current user's account info
client.users.getCurrentAccount().response { response, error in
print("*** Get current account ***")
if let account = response {
print("Hello \(account.name.givenName)!")
} else {
print(error!)
}
}
// List folder
client.files.listFolder(path: "").response { response, error in
print("*** List folder ***")
if let result = response {
print("Folder contents:")
for entry in result.entries {
print(entry.name)
}
} else {
print(error!)
}
}
// Upload a file
let fileData = "Hello!".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
client.files.upload(path: "/hello.txt", body: fileData!).response { response, error in
if let metadata = response {
print("*** Upload file ****")
print("Uploaded file name: \(metadata.name)")
print("Uploaded file revision: \(metadata.rev)")
// Get file (or folder) metadata
client.files.getMetadata(path: "/hello.txt").response { response, error in
print("*** Get file metadata ***")
if let metadata = response {
if let file = metadata as? Files.FileMetadata {
print("This is a file with path: \(file.pathLower)")
print("File size: \(file.size)")
} else if let folder = metadata as? Files.FolderMetadata {
print("This is a folder with path: \(folder.pathLower)")
}
} else {
print(error!)
}
}
// Download a file
let destination : (NSURL, NSHTTPURLResponse) -> NSURL = { temporaryURL, response in
let fileManager = NSFileManager.defaultManager()
let directoryURL = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
// generate a unique name for this file in case we've seen it before
let UUID = NSUUID().UUIDString
let pathComponent = "\(UUID)-\(response.suggestedFilename!)"
return directoryURL.URLByAppendingPathComponent(pathComponent)
}
client.files.download(path: "/hello.txt", destination: destination).response { response, error in
//client.files.download(path: "/hello.txt").response { response, error in
if let (metadata, url) = response {
print("*** Download file ***")
let data = NSData(contentsOfURL: url)
print("Downloaded file name: \(metadata.name)")
print("Downloaded file url: \(url)")
print("Downloaded file data: \(data)")
} else {
print(error!)
}
}
} else {
print(error!)
}
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You're reading a blog post from May about an early preview version of the SDK. Lots of things have changed since that post! Check out https://www.dropbox.com/developers/documentation/swift#tutorial for an up-to-date tutorial.
I believe you want users.getCurrentAccount and files.listFolder.
Related
I'm reading a file using UIDocumentPickerViewController:
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
guard let url = urls.first else {
return
}
openDocument(at: url) { result in
if let .success(data) = result {
save(url)
}
}
}
func openDocument(at url: URL, completion: (Result<Data, LoadError>) -> Void) {
if startAccessingSecurityScopedResource() {
defer { stopAccessingSecurityScopedResource() }
do {
let data = try Data(contentsOf: self)
return .success(data)
} catch {
return .failure(.genericError(error))
}
}
return .failure(.noAccess)
}
So after reading the document I make a copy of the bookmarkData of its URL:
func save(_ url: URL) {
NSFileCoordinator().coordinate(readingItemAt: url, error: &error) { coorindatedURL in
if coorindatedURL.startAccessingSecurityScopedResource() {
defer { coorindatedURL.stopAccessingSecurityScopedResource() }
do {
let bookmarkData = try coorindatedURL.bookmarkData()
// save bookmarkData with the url
} catch {
}
}
}
}
Then every time I read the document I read from saved bookmarkData:
var stale = false
if let url = try? URL(resolvingBookmarkData: bookmarkData, bookmarkDataIsStale: &stale), stale == false {
if startAccessingSecurityScopedResource() {
defer { stopAccessingSecurityScopedResource() }
do {
let data = try Data(contentsOf: url)
} catch {
}
}
}
It works at first, and for 1 or 2 days, but after a few days I started getting this error:
Error Domain=NSCocoaErrorDomain Code=260 "The file FILENAME couldn’t be opened because there is no such file." UserInfo={NSFilePath=/private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/PATH/TO/FILE.doc, NSUnderlyingError=0x2830cae80 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
I checked the file is still there in my iCloud folder, and the stale flag is false. So I'm not sure what the problem is?
Thanks!
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);
},
Here's the code I've tried so far:
client?.files.download(path: "/AlloyTest/\(imageName)").response { response, error in
if let response = response {
let responseMetadata = response.0
print(responseMetadata)
let fileContents = response.1
print(fileContents)
} else if let error = error {
print(error)
}
}
.progress { progressData in
print(progressData)
}
This is the error I'm getting when trying the function below:
API route error - {
".tag" = path;
path = {
".tag" = "not_found";
};
}
NEW CODE
func getImage(imageName: String, completion: #escaping (UIImage, NetworkingError) -> ()) {
// Get Image from dropbox
// Download to Data
client?.files.listFolder(path: "/AlloyTest").response { response, error in
if let response = response {
let entries = response.entries
print("ENTRIES:", entries)
} else if let error = error {
print(error)
}
}
}
A path/not_found error indicates that there was nothing at the specified path, in this case "/AlloyTest/\(imageName)", in the connected Dropbox account. Make sure you provide the correct path.
For example, you can list the contents of any particular folder to get the correct path values of its contents using listFolder/listFolderContinue. The path for any particular returned item is Metadata.pathLower.
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 just updated my project to the latest version of Firebase Storage and I am now getting a warning:
downloadURL() is deprecated: Use StorageReference.downloadURLWithCompletion() to obtain a current download URL.
I looked at the Firebase image upload documentation but it still references using downloadURL() which is now depreciated. In the code below I am getting the download URL of the image as a String. The code works but now to be updated since downloadURL() is depreciated
uploadProfilePicTask.observe(.success) { snapshot in
guard let profilePicStringURL = snapshot.metadata?.downloadURL()?.absoluteString else { return }
...
Here is my attempted updated. I tried the code below with the new downloadURLWithCompletion() but something in snapshot.metadata?.storageReference? is returning nil so I am not able to retrieve the url String. Does anyone know how to use the new downloadURLWithCompletion() appropriately below?
uploadProfilePicTask.observe(.success) { snapshot in
snapshot.metadata?.storageReference?.downloadURL { URL, error in
if let urlString = URL?.absoluteString {
// Do something
} else {
return
}
}
Basically not using the metadata but instead just getting the url after the success of your observe event. Since it's successful and you know it's there, you can download the URL. It's there in their docs to 'Generate a download URL'. Below, I'm assuming your StorageReference is uploadProfilePicTask.
uploadProfilePicTask.downloadURL(completion: { (url, error) in
if (error == nil) {
if let downloadUrl = url {
// Make you download string
let downloadString = downloadUrl.absoluteString
}
} else {
// Do something if error
}
})
I had the same problem, but I fixed it with this code:
uploadTask.observe(.success) { snapshot in
guard let imageURL = snapshot.metadata?.storageReference?.downloadURL(completion: { (url, error) in if error != nil {
print(error as Any)
} else { //add all you want
}
}) else { return }
let imageStr = String(describing: imageURL)
DBService.manager.updatePhoto(profileImageUrl: imageStr)
AuthService.manager.updatePhoto(urlString: imageStr)
}
}