2
votes

I am trying to connect to a media server via NSURLSession and list all available directories/files at that url (i.e. ftp://mediaServer.local), then traverse down them until I find the file I am looking for.

I am able to provide a url and spit out it's top level files/directories using 'dataTaskWithRequest', but the parsed NSData is not really readable so that I can actually append the file/directory to the original URL and then traverse down the path.

Here is what is spit out:

Results: drwxrwsr-x   11 65534    65534       65536 Sep 19 15:36 Public

The directory I would then want to traverse into is the 'Public' directory, so the url I want to use next should be ftp://mediaServer.local/Public/.

How can I parse the NSData object to be easier to just get the actual names of all readable files/directories? I tried parsing the NSData result into a JSON dictionary, but that doesn't work. Any suggestions?

Here is my code:

// Url used = ftp://mediaServer.local/
func startRequestWithUrl(url: NSURL)
{
    let request = NSURLRequest(URL: url)
    let session = NSURLSession.sharedSession()
    let task = session.dataTaskWithRequest(request) { (data, response, error) -> Void in
        print("Data: \(data)")
        print("Response: \(response)")
        print("Error: \(error)")

        if let data = data, let results = NSString(data: data, encoding: NSASCIIStringEncoding)
        {
            print("Results: \(results)")

            do
            {
                let dict = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments) as? NSDictionary
                print("Dict: \(dict)")
            }
            catch let caught as NSError
            {
                print("Caught: \(caught)")
            }
            catch
            {
                // Something else happened.
                print("Error parsing data.")
            }
        }

    }
    task.resume()
}

UPDATE:

With the below answer, I tried spitting out each file/directory into a single string and break it up into an array, but it doesn't seem to break the components apart properly as I only get single-item arrays with the full file path string still.

Code:

if let data = data, let results = NSString(data: data, encoding: NSASCIIStringEncoding)
        {
            print("Results: \(results)")
            let lines = results.componentsSeparatedByString("\n")
            for line in lines
            {
                let fields = line.componentsSeparatedByString("\t")
                print("Line: \(line) - Fields: \(fields)")
            }
        }

Results:

Results: drwxrwsr-x   11 65534    65534       65536 Sep 19 15:36 Public

Line: drwxrwsr-x   11 65534    65534       65536 Sep 19 15:36 Public
- Fields: ["drwxrwsr-x   11 65534    65534       65536 Sep 19 15:36 Public\r"]
Line:  - Fields: [""]
1
A couple problems: it looks like you should be separating lines on \r\n instead of just \n. This will change from one FTP server to the next. It's pretty clear \t is not being used anywhere. Instead you'll want scan each line using NSScanner, to split it up based on whitespace character sets (until the last column, where you'll scan until the end of the line including whitespace). Since you're using NSScanner anyway, you should probably use it to split up lines as well. NSScanner is very fast and memory efficient, it will handle large directories better than componentsSeparatedByAbhi Beckert

1 Answers

0
votes

The results are just a text directory list, just parse the text. You can use componentsSeparatedByString:@"\n: to get an array of entries. For each entry you can use componentsSeparatedByString:@" : (possibly @"\t") to get the file name.

Directories can be determined by the first letter "d".

You will want to ignore certain files and directories of course.

Other methods include regular expressions and NSScanner. You will want to ignore certain files and directories of course.

This is all rather simple parsing.