download file in osx application (cocoa / wkwebview))

Hi all,


I have a question. I got a webview (hidden) and im logged in a company website.

all good so far.


But i want to download a file. But its not as simple as https://www.apple.com/mypdf.pdf.


The url is for example like https://www.apple.com/getfile?monitor=1234567. In a normal browser it will download a mp3 file.


I use this code in FileDownloader.swift:

import Foundation

class FileDownloader : NSObject, URLSessionDownloadDelegate {

    var url : URL?
    // will be used to do whatever is needed once download is complete
    var yourOwnObject : NSObject?

    init(_ yourOwnObject : NSObject)
    {
        self.yourOwnObject = yourOwnObject
    }

    //is called once the download is complete
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)
    {
        //copy downloaded data to your documents directory with same names as source file
        let documentsUrl =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
        //FileManager.default.

        let destinationUrl = documentsUrl!.appendingPathComponent(url!.lastPathComponent)
        let dataFromURL = NSData(contentsOf: location)
        dataFromURL?.write(to: destinationUrl, atomically: true)

        //now it is time to do what is needed to be done after the download
        //yourOwnObject!.callWhatIsNeeded()
    }

    //this is to track progress
    private func URLSession(session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)
    {
    }

    // if there is an error during download this will be called
    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
    {
        if(error != nil)
        {
            //handle the error
            print("Download completed with error: \(error!.localizedDescription)");
        }
    }

    //method to be called to download
    func download(url: URL)
    {
        self.url = url

        //download identifier can be customized. I used the "ulr.absoluteString"
        let sessionConfig = URLSessionConfiguration.background(withIdentifier: url.absoluteString)
        let session = Foundation.URLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
        let task = session.downloadTask(with: url)
        task.resume()
    }

}


and in my viewcontroller i use this to start the download.


let strURL ="https://www.apple.com/getfile?monitor=1234567"
let url = URL(string: strURL)

FileDownloader(url! as NSObject).download(url: url!)


It works but i get one file named getfile without an extension in the documents folder and its always 10.8 bytes.


How can I get the response from the website and download the mp3 file.


i hope someone can point me in the right direction.

Replies

I suspect that the download has failed on the server. You should look at the

statusCode
property of the
URLResponse
(you’ll have to cast it to an
HTTPURLResponse
to access that property). The data you download may also contain a textual description of why it failed.

The most likely cause of this problem is authorisation.

WKWebView
and
URLSession
do not share an authorisation context, meaning that the authorisation done in the
WKWebView
does not also apply to your
URLSession
. So the server doesn’t know that the download request is coming from the same client. The correct way to fix this depends on the server, because different servers use different authorisation strategies.

One common strategy is for the server to send the client a cookie and then use that cookie for authorising subsequent requests. You can get this cookie from

WKWebView
using
WKHTTPCookieStore
and then apply it to your
URLSession
request using various Foundation-level APIs. However, it’s hard to offer specific advice on this front because the exact nature of such cookies varies by server.

If the web server doesn’t document how it does authorisation, and you can figure this out directly, you can use the technique from my Debugging HTTP Server-Side Errors post to compare a successful request (for example, from Safari) against an unsuccessful one (from your app).

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks Quinn,


I will look into that and will get back with info.