Here is my situation: i'm calling file locally on my ios application ( Running in Swift).
If the file is a jpg, one action happen, if the file is a mp4, another action happen.
For this i'musing this code:
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)
/* END DOWNLOAD + READ LOCALY */
if (fileURL.pathExtension?.hasPrefix("jpg"))! {
Swift.print("THIS IS A JPG")
}
else if (fileURL.pathExtension == "mp4") {
Swift.print("THIS IS A MP4")
}
This works perfectly.
What i need to do now is instead of calling th eifle locally, to calling it form an URL.
I read my file from an url by:
videoVRView.load(from: URL(string: "\(posts[selectedIndexPath].link)")
Which work.
But from that, the action is not working, i've try the following:
if ((from: URL(string: "\(posts[selectedIndexPath].link)").hasPrefix("jpg"))! {
Swift.print("THIS IS A JPG")
}
else if ((from: URL(string: "\(posts[selectedIndexPath].link)") == "mp4") {
Swift.print("THIS IS A MP4")
}
Without any success !!
Does anybody know how is this achievable ?
Thanks a lot =)
-- EDIT --
What im trying to do is th efollowing to resume:
at th emoment i call image locally via:
imageVRView.load(UIImage(named: "\(documentsPath)/\(fileName.lastPathComponent)" ),
of: GVRPanoramaImageType.stereoOverUnder)
I try instead to use:
imageVRView.load(UIImage(named: "\(posts[selectedIndexPath].link)" ),
of: GVRPanoramaImageType.stereoOverUnder)
Without success . . . . I need to call the image via this method ... any idea ?
Thanks a lot !
You can make a URL request for the url header using the httpMethod HEAD to check your url mime type without the need to download the data first:
let link = "https://www.dropbox.com/s/sk46eyglvijlrec/horse.jpg?dl=1"
let url = URL(string: link)!
var request = URLRequest(url: url)
request.httpMethod = "HEAD"
URLSession.shared.dataTask(with: request) { _ , response , _ in
guard let response = response, (response as? HTTPURLResponse)?.statusCode == 200 else { return }
DispatchQueue.main.async() {
print("mimeType", response.mimeType ?? "nil") // image/jpeg
print("suggestedFilename:", response.suggestedFilename ?? "no suggestedFilename") // horse.jpg
print("expectedContentLength:", response.expectedContentLength ?? "nil") // 352614
print("textEncodingName:", response.textEncodingName ?? "nil")
print("url:", response.url ?? "nil") // "https://dl.dropboxusercontent.com/content_link/RNrhGtvroTLU1Gww7eQo1N1ePRiix68zsqZJ1xWPjKm3pmOUNQwNVntbPuFG4jZ8/file?dl=1"
}
}.resume()
Related
This portion of the code is supposed to download a txt file from a website. By running this code it is able to successfully download the file from the website and place it into the app's Documents directory. I am able to see where the file is stored because in the last couple of lines in the code it prints out the location of the file. However, I am not able to get the file name that was recently downloaded. The goal is for me to try to get the name of the file so that I can be able to open it and read from it. What are my options in approaching this? What am I missing in this block of code that is preventing me from getting the name of the file that was recently downloaded?
guard let url1 = URL(string: website) else { return }
//This portion of the code focuses on creating a download task with a completion handler
//Completion handler moves the downloaded file to the app's directory
let downloadTask = URLSession.shared.downloadTask(with: url1) {
urlOrNil, responseOrNil, errorOrNil in
// check for and handle errors:
// * errorOrNil should be nil
// * responseOrNil should be an HTTPURLResponse with statusCode in 200..<299
guard let fileURL = urlOrNil else { return }
do {
let documentsURL = try
FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false)
let savedURL = documentsURL.appendingPathComponent(
fileURL.lastPathComponent)
try FileManager.default.moveItem(at: fileURL, to: savedURL)
} catch {
print ("file error: \(error)")
}
}
downloadTask.resume()
//If you want to receive progress updates as the download proceeds, you must use a delegate.
var urlSession = URLSession(configuration: .default, delegate: self as? URLSessionDelegate, delegateQueue: nil)
func startDownload(url1: URL) -> String? {
let downloadTask = urlSession.downloadTask(with: url1)
let fname = downloadTask.response?.suggestedFilename
downloadTask.resume()
return fname
//self.downloadTask = downloadTask
}
let name = startDownload(url1: url1)
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) as NSArray
let documentsDir = paths.firstObject as! String
print("Path to the Documents directory\n\(documentsDir)")
You can get the name of the file at a given path by initialising a URL object from the path:
let name = URL(fileURLWithPath: yourPath).lastPathComponent
This returns an optional string. The name will be automatically unescaped, so it will be human-readable (no percent encoding).
The filename should be available to you from your fileURL variable, as this is where you got the filename in order to save it:
let name = fileURL.lastPathComponent
I have a query on a Cloud CKRecord, which checks to see if a documents exists (i.e. has been uploaded as an CKAsset) and if not checks if a URL exists (i.e. has been uploaded as a String). All works well if either exist on their own for a given record, however if both exist when clicking on the link nothing happens.
I feel it is something to do with the if and else if statements -
if filename1 != nil {
let asset1 = record.object(forKey: "courseDocument1") as? CKAsset
let filename = record.object(forKey: "courseDocument1Filename") as! String
let path = (NSTemporaryDirectory() as NSString).appendingPathComponent(filename)
let doc1Data : NSData? = NSData(contentsOf:(asset1?.fileURL)!)
do {
try doc1Data!.write(to: URL(fileURLWithPath: path), options: .atomic)
let url = URL(fileURLWithPath: path)
let urlRequest = URLRequest(url: url)
self.courseDoc1WebView?.loadRequest(urlRequest)
self.venueDocButton1.setTitle(cseDocument1,for: [])
self.venueDocButton1.isHidden = false
self.courseDocumentLabel.isHidden = false
} catch {
print(error)
}
} else if cseDocument1URL != nil && filename1 == nil {
let url1 = URL (string: cseDocument1URL!)
let request1 = URLRequest(url: url1! as URL );
self.courseDoc2WebView.loadRequest(request1 as URLRequest);
self.venueDocButton1.setTitle(cseDocument1,for: [])
self.venueDocButton1.isHidden = false
self.courseDocumentLabel.isHidden = false
} else {
print("No Document Found")
}
Any thoughts?
This turned out to be a simple typo rather than logic -
self.courseDoc2WebView.loadRequest(request1 as URLRequest);
which should actually be -
self.courseDoc1WebView.loadRequest(request1 as URLRequest);
This was solved by printing responses and using the debugger - thanks Phillip Mills
Duncan C, you make a good point too - thank-you.
I am trying to upload a video to a server file through Alamofire but I couldn't get the "data" going to be passed..its always nil
var videoURL = NSURL(string: "")
//returns Optional(file:///private/var/mobile/Containers/Data/Application/1FB40086-228B-4011-A9D4-7874E2EEF9F4/tmp/4A6AAD76-B899-4B67-8E96-925DA4AE9E93.mov)
let videodata = NSData(contentsOfFile: (videoURL?.absoluteString)!)
//nil
let url = NSURL(fileURLWithPath: (videoURL?.absoluteString)!)
let videodata = NSData(contentsOf: url as URL)
//nil
If I get data would lead a way for me to do this:
Alamofire.upload(multipartFormData: { multipartFormData in
multipartFormData.append (videodata as! Data, withName: "file", fileName: "file.mov", mimeType: "video/quicktime")
enter code here
EDIT::
thank you guys, with your help I have struggled my way out of there to this file not found error, but I can see the file is being saved in my gallery, any clue would save my day.
print (videoURL!)
//returns file:///private/var/mobile/Containers/Data/Application/3F280477-DA16-4A67-AE60-D6247143352E/tmp/1E4AC002-6AD0-41E1-9E0D-A09B697F81F7.mov
print (videoURL!.path!)
// returns /private/var/mobile/Containers/Data/Application/3F280477-DA16-4A67-AE60-D6247143352E/tmp/1E4AC002-6AD0-41E1-9E0D-A09B697F81F7.mov
var videoData = NSData()
let path = videoURL!.path!
if FileManager.default.fileExists(atPath: path) {
}else {
print("Could not fin file at url: \(videoURL!.path!)")
// here it throws file not found
}
In Swift 3 use native URL and Data instead of NSURL and NSData.
if let videoURL = URL(string: urlString), let videodata = try? Data(contentsOf: videoURL) {
//Add code of Alamofire here
}
Using absoluteString returns a string that includes file:// at the beginning and you don't want that. You need to return the path of the URL
guard let videoPathString = videoURL.path as? String else {
//handle error here if you can't create a path string
return
}
var videoData = NSData()
//check if file exists at this path first
if (NSFileManager.defaultManager().fileExistsAtPath(videoPathString)) {
videoData = NSData(contentsOfFile: NSString(videoPathString))
} else {
//if file does not exist at that path, handle here
}
I know how to get a remote URL in Swift
let remoteURL = NSURL(string: "https://myserver/file.txt")!
I know how to get a local URL in Swift
let localURL = NSURL(fileURLWithPath: documentsFolder + "/my_local_file.txt")
and unfortunately this does not work
NSFileManager.defaultManager().copyItemAtURL(remoteURL, toURL: localURL)
with the following error
The file “file.txt” couldn’t be opened because URL type https isn’t supported.
Is there a way how to perform this?
You can use NSURLSessionDownloadTask to download the file:
func downloadFile(url: URL) {
let downloadRequest = URLRequest(url: url)
URLSession.shared.downloadTask(with: downloadRequest) { location, response, error in
// To do check resoponse before saving
guard let tempLocation = location where error == nil else { return }
let documentDirectory = FileManager.default.urlsForDirectory(.documentDirectory, inDomains: .userDomainMask).last
do {
let fullURL = try documentDirectory?.appendingPathComponent((response?.suggestedFilename!)!)
try FileManager.default.moveItem(at: tempLocation, to: fullURL!)
print("saved at \(fullURL) ")
} catch NSCocoaError.fileReadNoSuchFileError {
print("No such file")
} catch {
// other errors
print("Error downloading file : \(error)")
}
}.resume()
}
let stringURL = "https://wordpress.org/plugins/about/readme.txt"
downloadImage(url: URL(string: stringURL)!)
Update: SWIFT 2.2
func downloadFile(url: NSURL) {
let downloadRequest = NSURLRequest(URL: url)
NSURLSession.sharedSession().downloadTaskWithRequest(downloadRequest){ (location, response, error) in
guard let tempLocation = location where error == nil else { return }
let documentDirectory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first
let fullURL = documentDirectory?.URLByAppendingPathComponent((response?.suggestedFilename)!)
do {
try NSFileManager.defaultManager().moveItemAtURL(tempLocation, toURL: fullURL!)
} catch NSCocoaError.FileReadNoSuchFileError {
print("No such file")
} catch {
print("Error downloading file : \(error)")
}
}.resume()
}
let stringURL = "https://wordpress.org/plugins/about/readme.txt"
let url = NSURL.init(string: stringURL)
downloadFile(url!)
You should download it first, then save it to a local file.
Code example can be found here: (using AFNetworking)
How I properly setup an AFNetworking Get Request?
I have the following Swift extension on NSURL
public extension NSURL {
func getQueryItemValueForKey(key: String) -> String? {
guard let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false) else {
return nil
}
guard let queryItems = components.queryItems else { return nil }
return queryItems.filter {
$0.name == key
}.first?.value
}
}
I am writing unit tests for it but I am unable to get 100% code coverage as I don't seem to be able to get NSURLComponents(URL: self, resolvingAgainstBaseURL: false) to return nil. From what I understand, this requires a malformed URL but I am struggling to create one.
I have tried:
let url = NSURL(string: "")
let url = NSURL(string: "http://www.example")
let url = NSURL(string: "http://www.exam ple.com")
let url = NSURL(string: "http://www.example.com/?param1=äëīòú")
And some others that I lost track of. I know this is probably something blatantly obvious but i'm lost at the moment. So, how do I create a malformed URL in Swift?
As found in my research, you can produce a url that is malformed for NSURLComponents but not for NSURL by using negative port number (probably there are more cases but not sure):
let example = "http://example.com:-80/"
let url = NSURL(string: example)
print("url:\(url)") //prints out url:Optional(http://example.com:-80/)
if let url = url {
let comps = NSURLComponents(URL: url, resolvingAgainstBaseURL: false)
print("comps:\(comps)") //prints out comps:nil
}