How to download all files from dropbox synchronously in swift? - swift

Using SwiftyDropbox download method to download all files. But, i found progress block showing data all together of different files, not downloading files in a way that downloading of one file start after completing the previous one.
Here, is the code used :
DropboxClientsManager.authorizedClient?.files
.download(path: entry.pathLower!, overwrite: true, destination: destination)
.response { response, error in
if let response = response {
print(response)
}
else if let error = error {
print(error)
}
}
.progress { progressData in
print(progressData)
}

Related

Firebase Storage and Swift - download task handling

I have a download task to get the video file. I checked the documentation about the download task but I don't see anything about handling the existing files.
Does the download task checks the existing file, then checks if it need to be resumed or leaves it alone?
If the download task fails in the middle of downloading, will the incomplete file still there?
If it don't overwrite the file, how do I compare the files in local and remote (file size? or MD5) to verify that I don't need to download the file?
Scenario - I have AppDelegateManager to download all of the videos beforehand. I don't want to download the videos each time the app is opened and wasn't sure if the videos were overwritten or not.
func getVideo(fileName : String, localUrl : URL, completion : #escaping (_ success : Bool) -> Void) {
let storage = Storage.storage()
let pathReference = storage.reference(withPath: FirebaseDirectoryNames.videos.rawValue + "/" + fileName)
let downloadTask = pathReference.write(toFile: localUrl) { url, error in
if let error = error {
os_log("error : ", log: self.tag, type: .debug, error.localizedDescription)
completion(false)
} else {
completion(true)
}
}
}

Get top of remote file in Swift

There is a line in multiple files via the Internet. I want to avoid download the entire file. Each file may be long or short. The required line is usually about line 15 - always different, but always within the first 500 bytes.
Is there a way I can get just the top part of a remote file?
I can then use a regex pattern to find the required line.
Although I know how to download a file in a temp. location and copy it to a proper location, I think that process is too much and wasteful.
This is an example:
class func load(url: URL, to localUrl: URL, completion: #escaping () -> ()) {
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)
let request = try! URLRequest(url: url, method: .get)
let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
// Success
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
print("Success: \(statusCode)")
}
do {
try FileManager.default.copyItem(at: tempLocalUrl, to: localUrl)
completion()
} catch (let writeError) {
print("error writing file \(localUrl) : \(writeError)")
}
} else {
print("Failure: %#", error?.localizedDescription);
}
}
task.resume()
}
PS. It would also be helpful if you could include a method to find a line beginning with, say "abc=xyz", where I want "xyz".
To only download partial content, you need a server that supports sending ranges. To test this, make a HEAD request and check if the server responds with an Accept-Range: bytes header. If so, you can request partial content by adding a header like Range: bytes=0-499 to your GET requests to only receive the initial 500 bytes.

File upload using Swift Vapor 3.0

I'm trying to create a simple vapor service so I can upload video files (one at a time) through an api.
From my app I'm uploading the video file using Alamofire:
func uploadVideo(video: URL) {
Alamofire.upload(videoFileURL, to: "http://localhost:8080/upload").responseString { response in
debugPrint(response)
}
}
The vapor controller method is like this (this is where I don't know how to do it):
func upload(_ req: Request) throws -> String {
let data = try req.content.decode(Data.self).map(to: Data.self) { video in
try Data(video).write(to: URL(fileURLWithPath: "/Users/eivindml/Desktop/video.mp4"))
return Data(video)
}
return "Video uploaded";
}
How do I get the video file from the request and into the right format so I can write it do disk?
The method upload() is called correctly etc, as it works if I just have the last return statement.
Looking at your function it appears you're not handling your future response correctly, or extracting the data.
func upload(_ req: Request) throws -> Future<String> {
return try req.content.decode(File.self).map(to: String.self) { (file) in
try file.data.write(to: URL(fileURLWithPath: "/Users/eivindml/Desktop/\(file.filename)"))
return "File uploaded"
}
}
See if this helps.

keep track of already downloaded files with `alamofire`

how can i keep a track or record of already downloaded files in alamofire swift 2.1 so that i don t have to download the same file again ? do we have any native method for that provided by alamofire or we have to do a check before downloading any file on our directory if we already have file with that name there ???? i'm confused on how to accomplish this with a proper approach
if anybody would clear my confusion about this then it'll be so helpful for me thanks
UPDATE:
let documentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let fileUrl = documentsURL.URLByAppendingPathComponent(suggestedFileName)
print(fileUrl)
if !(NSFileManager.defaultManager().fileExistsAtPath(fileUrl.path!)){
self.suggestedFileName = (self.request?.response?.suggestedFilename)! // here how can i get the suggested download name before starting the download preocess ???
print("\(destination)")
request = Alamofire.download(.GET, "http://contentserver.adobe.com/store/books/GeographyofBliss_oneChapter.epub", destination: destination)
.progress { bytesRead, totalBytesRead, totalBytesExpectedToRead in
print(totalBytesRead)
// This closure is NOT called on the main queue for performance
// reasons. To update your ui, dispatch to the main queue.
dispatch_async(dispatch_get_main_queue()) {
print("Total bytes read on main queue: \(totalBytesRead)")
self.progressView.setProgress(Float(totalBytesRead) / Float(totalBytesExpectedToRead), animated: true)
}
}
.response { _, _, _, error in
if let error = error {
print("Failed with error: \(error)")
} else {
print("Downloaded file successfully")
}
}
}else {
print("file already exists")
}
in the above update am trying to get the suggestedFileName which is generated by alamofire but there's one problem when am trying to get sugestedFileName like this : suggestedFileName = (request?.response?.suggestedFilename)! in viewdidload am getting a null exception off course because there's no suggestedFileName because download not yet started so my question is that how can i get the suggestedFileName from response before starting the download ??
According to the docs https://github.com/Alamofire/Alamofire#downloading, you can download to a file. If your file destinations names are predictable, you could simply check to see if the contents of the file exists. For example if your are downloading data:
if let data = NSData(contentsOfURL: yourDestinationURL) {
//Do your stuff here
}
else {
//Download it
}
If you want consistency between names I suggest you avoid the Alamofire suggested destination and do this instead:
let path = NSFileManager.defaultManager().URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask)[0] as NSURL
let newPath = path.URLByAppendingPathComponent(fileName)
Alamofire.download(.GET, "https://httpbin.org/stream/100", destination: { _ in
newPath //You have to give the destination in this closure. We could say 'return newPath' instead, they're the same thing.
})
.progress({ _ in
//progress stuff
})
.response { _, _, data, _ in
//Handle response once it's all over
}

how should I prevent the UI from being stuck when unzipping file with ZIP in swift

I am trying to print the progress on unzipping a file on the swiftUI. but each time the UI gets stuck while doing so. I am using ZIP as a 3rd part library.
I tried this code to make unzipping on a different thread
utils.initWindow()
DispatchQueue.main.async {
self.utils.unzipFile(fileLocation: URL(string: "/Users/user/Downloads/Archive.zip")!, destination: URL(string: "/Users/user/Downloads/testunzip")!)
}
and this is how I implemented the function unzipFile
public func unzipFile(fileLocation: URL, destination: URL){
self.launcher.addLog(log: "Retrieving files")
do{
try Zip.unzipFile(fileLocation, destination: destination, overwrite: true, password: "", progress: { (progress) -> () in
print(progress)
self.launcher.setState(state: progress)
})
}
catch {
self.launcher.setState(state: progress)
print("Something went wrong")
}
}
PS: setState basically sets a value of a #Published variable on a #ObservedObject that control the Text on the UI and it works perfectly fine when I am printing the progress on a different function that prints the progress on downloading a file
Don't perform unzip or zip on main thread as it can be a heavy operation. Instead of main thread use
DispatchQueue.global(qos: .background).async {
}
Happy Coding!