Swift download with byte-range request - ios

I have allready implemented a download session, now what i wanna do is make it to download only a portion of that file. i know that its possible through the byte-range but im not sure how do i have to do that in swift. any help would be much appreciated. thanks.
#IBAction func btnStartDownload(sender: NSButton) {
let downloadUrl = NSURL(string:"http://www.joomlaworks.net/images/demos/galleries/abstract/7.jpg")
let sessionConfiguration:NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
let session:NSURLSession = NSURLSession(configuration: sessionConfiguration)
let sessionDownloadTask:NSURLSessionDownloadTask = session.downloadTaskWithURL(downloadUrl!, completionHandler: { (data, response, error) -> Void in
let data = NSData(contentsOfURL: data)
var fileManager:NSFileManager = NSFileManager.defaultManager()
var paths:NSArray = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
var documentsDirectory:NSString = paths[0] as NSString
var databasePath:NSString = documentsDirectory.stringByAppendingString("/\(response.suggestedFilename!)")
fileManager.createFileAtPath(databasePath, contents: data , attributes: nil)
NSLog("Database copied to\(databasePath)")
})
sessionDownloadTask.resume()
}

Related

Continue download on background / other screen on my ios app

I have a download function working perfectly, on click of my button, the file is being download correctly.
What I am trying to achieve, If I put the App in the background or change screen while it's downloading the file, I'd like the download to be continued. Currently if the App is in the background ,the download stop and user need to restart it from zero.
How is this possible to make ?? Below is my download function, I tried to add a background download without success.
func createDownloadTask() {
let downloadRequest = URLRequest(url: URL(string: "\(posts[selectedIndexPath].link)")!)
let session = Foundation.URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: OperationQueue.main)
downloadTask = session.downloadTask(with: downloadRequest)
downloadTask!.resume()
}
and
#IBAction func startDownload(_ sender: UIButton) {
let urlString = "\(posts[selectedIndexPath].link)"
DispatchQueue.global(qos: .default).async(execute: {
print("downloadVideo");
let url=NSURL(string: urlString);
let urlData=NSData(contentsOf: url! as URL);
if((urlData) != nil)
{
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let fileName = urlString as NSString;
let filePath="\(documentsPath)/\(fileName.lastPathComponent)";
DispatchQueue.main.async(execute: { () -> Void in
print(filePath)
urlData?.write(toFile: filePath, atomically: true);
print("video Saved to document directory of app");
self.downloadButton.alpha = 0;
self.progressView.alpha = 0;
self.cardboardButton.alpha = 1;
self.videoButton.alpha = 1;
self.removefile.alpha = 1;
})
}
})
}
You need to use UIBackgroundTaskIdentifier. You can start some task in background with beginBackgroundTask see:
https://developer.apple.com/reference/uikit/uiapplication/1623031-beginbackgroundtask.
System will give you some time and you can finish your task. If the time expire you will receive handler.See example that I use to upload a image
static var backgroundUpload:UIBackgroundTaskIdentifier?
static func praiseCollegue(praiseCollegueId:Int,image:UIImageView,praisedBy:Int,praiseText:String,praiseCategory:Int,successBlock: (()->())?,errorBlock: (()->())?){
backgroundUpload = UIApplication.shared.beginBackgroundTask(expirationHandler: {
if let task = self.backgroundUpload{
UIApplication.shared.endBackgroundTask(task)
}
})
let url = NSURL(string: "someUrl")
let request = NSMutableURLRequest(url: url! as URL)
request.httpMethod = "POST"
request.setValue(InfoManager.sharedInstance.tokenInfo?.accessToken, forHTTPHeaderField: "AccessToken")
let session = URLSession.shared
let task = session.dataTask(with: request as URLRequest) {
(
data, response, error) in
if let responseData = data{
do {
if let dict = try JSONSerialization.jsonObject(with: responseData, options: []) as? [String: AnyObject]{
if let errorCode = dict["errorCode"] as? Int{
if(errorCode == 1){
successBlock?()
if let task = self.backgroundUpload{
UIApplication.shared.endBackgroundTask(task)
}
}
else{
errorBlock?()
if let task = self.backgroundUpload{
UIApplication.shared.endBackgroundTask(task)
}
}
}
}
}
}
}
task.resume()
}

Save file to temp directory, then call back the url from that temp directory

I'm using this code for user to download a video to a temporary DIrectory:
#IBAction func startDownload(_ sender: UIButton) {
let videoImageUrl = "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"
DispatchQueue.global(qos: .default).async {
let url = NSURL(string: videoImageUrl);
let urlData = NSData(contentsOf: url! as URL);
if(urlData != nil)
{
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
let filePath="\(documentsPath)/tempFile.mp4";
DispatchQueue.main.async {
urlData?.write(toFile: filePath, atomically: true);
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: NSURL(fileURLWithPath: filePath) as URL)
}) { completed, error in
if completed {
print("Video is saved!")
}
}
}
}
}
}
Otherwise, when clicking on the button download, the App get frozen after sometime.
I'd like ideally the file to be save 'temporary' into the App, not to appear int he photolibrary of the Mobile.
How is this possible ?
Then, IS there a way to call back the file from that temporary directory ?
How this can be achieve in the process ?
Thanks a lot guys !
---- EDIT ---
#IBAction func startDownload(_ sender: UIButton) {
let urlString = "\(posts[selectedIndexPath].link)"
DispatchQueue.global(qos: .default).async(execute: {
//All stuff here
print("downloadVideo");
let url=NSURL(string: urlString);
let urlData=NSData(contentsOf: url! as URL);
if((urlData) != nil)
{
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let fileName = urlString as NSString;
let filePath="\(documentsPath)/\(fileName.lastPathComponent)";
DispatchQueue.main.async(execute: { () -> Void in
print(filePath)
urlData?.write(toFile: filePath, atomically: true);
print("video Saved to document directory of app");
})
}
})
}
#IBAction func playDownload(_ sender: UIButton) {
let urlString = "\(posts[selectedIndexPath].link)"
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let fileName = urlString as NSString;
let filePath="\(documentsPath)/\(fileName.lastPathComponent)";
let fileURL = NSURL.init(fileURLWithPath: filePath)
let request = NSURLRequest.init(url: fileURL as URL)
print(fireURL)
print("video called from document directory of app");
// creating webView to play video, you can use player as per requirement
let webView = UIWebView.init(frame: CGRect.init(x: 0, y: 0, width: 320, height: 320))
webView.loadRequest(request as URLRequest)
self.view.addSubview(webView)
}
in the console this is what I get:
/var/mobile/Containers/Data/Application/0A2D4FC0-F001-4711-916C-86C34CC5B71A/Documents/Cabin_Mono_4K_60fps.mp4?alt=media&token=32faeba5-3d9b-4090-9340-3e28986db5fa
video Saved to document directory of app
file:///var/mobile/Containers/Data/Application/0A2D4FC0-F001-4711-916C-86C34CC5B71A/DocumentsCabin_Mono_4K_60fps.mp4%3Falt=media&token=32faeba5-3d9b-4090-9340-3e28986db5fa
Below method will save video to documents directory(specific for app) :
func downloadVideo()
{
let urlString = "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"
DispatchQueue.global(qos: .default).async(execute: {
//All stuff here
print("downloadVideo");
let url=NSURL(string: urlString);
let urlData=NSData(contentsOf: url! as URL);
if((urlData) != nil)
{
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let fileName = urlString as NSString;
let filePath="\(documentsPath)/\(fileName.lastPathComponent)";
let fileExists = FileManager().fileExists(atPath: filePath)
if(fileExists){
// File is already downloaded
}
else{
//download
DispatchQueue.main.async(execute: { () -> Void in
print(filePath)
urlData?.write(toFile: filePath, atomically: true);
print("videoSaved");
})
}
}
})
}
Wherever you want to get video, you can read it from same document directory as below:
func GetVideo() {
let urlString = "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let fileName = urlString as NSString;
let filePath="\(documentsPath)/\(fileName.lastPathComponent)";
let fileURL = NSURL.init(fileURLWithPath: filePath)
let request = NSURLRequest.init(url: fileURL as URL)
// creating webView to play video, you can use player as per requirement
let webView = UIWebView.init(frame: CGRect.init(x: 0, y: 0, width: 320, height: 320))
webView.loadRequest(request as URLRequest)
self.view.addSubview(webView)
}

How to download image from Url using of NSURlConnection to save in phone cache

I am using NSUrlconnection to call to api but now i have also receive image from api so i don't know how to load the image & save into phones local memory because these images are further using in app . please help me. how to use & show image from local save.I am using below function to load the image but NSURLSession.sharedSession() are not going to inside the queue.
func saveImage(url:NSString,image_name1:NSString)
{
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: url as String)!, completionHandler: { (data, response, error) -> Void in
if error != nil {
print(error)
return
}
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let image = UIImage(data: data!)
var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory = paths[0]
let path = NSURL(fileURLWithPath: documentsDirectory).URLByAppendingPathComponent(image_name1 as String)!.absoluteString
print(" file path is \(path)")
let data = UIImagePNGRepresentation(image!)
data!.writeToFile(path!, atomically: true)
})
}).resume()
}
for save
var image = .... // However you create/get a UIImage
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let destinationPath = documentsPath.stringByAppendingPathComponent("filename.jpg")
UIImageJPEGRepresentation(image,1.0).writeToFile(destinationPath, atomically: true)
for cash
https://github.com/onevcat/Kingfisher
pod 'Kingfisher'
let url = URL(string: "url_of_your_image")
imageView.kf.setImage(with: url)
it's automatic cash images
Try this :
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
imageView.image = UIImage(data: data!)
From : https://stackoverflow.com/a/27517280/3901620

Open p12 files on ios device

I have this requirement to download .p12 file(certificate) from a vendor and make it available on my app for the user to install it on to his device.
Now If I attach a .p12 file to email and when the recipient clicks on the file on iphone it will start installing I am just trying to get the same behavior.
As of now in my app I am able to download the p12 file and store it in the apps documents directory.
func saveCert(serialId : String){
let source = "https://myhost.com/serialId"
let url = NSURL(string: source)
let request = NSURLRequest(URL: url!)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if (error == nil) {
let statusCode = (response as! NSHTTPURLResponse).statusCode
print("Success: \(statusCode)")
let filename = self.getDocumentsDirectory().stringByAppendingPathComponent("test.p12")
print(filename)
data?.writeToFile(filename, atomically: true)
let filemgr = NSFileManager.defaultManager()
if filemgr.fileExistsAtPath(filename) {
print("File exists")
} else {
print("File not found")
}
}
else {
print("Faulure: %#", error!.localizedDescription);
}
});
task.resume()
}
Now i need to open this file so user will be taken to install profile screens. Please help.
Here is what you want to look at.
and here is an example of how to use it
import Security
let fileManager = NSFileManager.defaultManager()
var resourcePath:String = fileManager.currentDirectoryPath
resourcePath = resourcePath.stringByAppendingString("/dummy.p12")
if fileManager.fileExistsAtPath(resourcePath){
let p12Data: NSData = NSData(contentsOfFile: resourcePath)!
let key : NSString = kSecImportExportPassphrase as NSString
let options : NSDictionary = [key : "password_for_certificate"]
//create variable for holding security information
var privateKeyRef: SecKeyRef? = nil
var items : CFArray?
let securityError: OSStatus = SecPKCS12Import(p12Data, options, &items)
}
Hope that gets you most of the way there.
Edit:
After doing more research, I found this lib that will help you do everything you are looking to do.
Give it a try.

how to delete file from my iphone 's app memory. from file manager ios swift

i am storing my data in file manager in my app. now i want to delete specific data by code so how can i do this?
here is my code which i used for store data
var localURL : String
init()
{
let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
localURL = urls.first!.URLByAppendingPathComponent("podcasts").path!
createDirectory(localURL)
}
func downloadShow(slug: String, show: NSDictionary) {
SVProgressHUD.showWithStatus("Downloading...")
let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
let url = NSURL(string: show["file"] as! String)
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "GET"
let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
if (error == nil) {
let showFileName = url?.lastPathComponent
let programMP3Path = self.localURL + "/" + slug + "/" + showFileName!
let programDataPath = programMP3Path + ".dat"
data?.writeToFile(programMP3Path, atomically: true)
show.writeToFile(programDataPath, atomically: true)
print("Success")
print(showFileName)
SVProgressHUD.dismiss()
}
else {
// Failure
print("Faulure: \(error)");
}
})
task.resume()
}}
Not sure about session methods. Here's how to delete file in user temp directory, if that helps
let myFileName = "myFile.txt"
var fileManager = NSFileManager()
var tempDirectory = NSTemporaryDirectory()
let filePath = tempDirectory.stringByAppendingPathComponent(myFileName)
var error: NSError?
// also good idea to check before if the file is in the directory
let path = tmpDir.stringByAppendingPathComponent(isFileInDir)
fileManager.removeItemAtPath(path, error: &error)

Resources