-
-
Save kushwaha03/98903fe40619d615f63b4fc56f8946c2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import WebKit | |
struct MimeType { | |
var type:String | |
var fileExtension:String | |
} | |
protocol WKWebViewDownloadHelperDelegate { | |
func fileDownloadedAtURL(url:URL) | |
} | |
class WKWebviewDownloadHelper:NSObject { | |
var webView:WKWebView | |
var mimeTypes:[MimeType] | |
var delegate:WKWebViewDownloadHelperDelegate | |
init(webView:WKWebView, mimeTypes:[MimeType], delegate:WKWebViewDownloadHelperDelegate) { | |
self.webView = webView | |
self.mimeTypes = mimeTypes | |
self.delegate = delegate | |
super.init() | |
webView.navigationDelegate = self | |
} | |
private var fileDestinationURL: URL? | |
private func downloadData(fromURL url:URL, | |
fileName:String, | |
completion:@escaping (Bool, URL?) -> Void) { | |
webView.configuration.websiteDataStore.httpCookieStore.getAllCookies() { cookies in | |
let session = URLSession.shared | |
session.configuration.httpCookieStorage?.setCookies(cookies, for: url, mainDocumentURL: nil) | |
let task = session.downloadTask(with: url) { localURL, urlResponse, error in | |
if let localURL = localURL { | |
let destinationURL = self.moveDownloadedFile(url: localURL, fileName: fileName) | |
completion(true, destinationURL) | |
} | |
else { | |
completion(false, nil) | |
} | |
} | |
task.resume() | |
} | |
} | |
private func getDefaultFileName(forMimeType mimeType:String) -> String { | |
for record in self.mimeTypes { | |
if mimeType.contains(record.type) { | |
return "default." + record.fileExtension | |
} | |
} | |
return "default" | |
} | |
private func getFileNameFromResponse(_ response:URLResponse) -> String? { | |
if let httpResponse = response as? HTTPURLResponse { | |
let headers = httpResponse.allHeaderFields | |
if let disposition = headers["Content-Disposition"] as? String { | |
let components = disposition.components(separatedBy: " ") | |
if components.count > 1 { | |
let innerComponents = components[1].components(separatedBy: "=") | |
if innerComponents.count > 1 { | |
if innerComponents[0].contains("filename") { | |
return innerComponents[1] | |
} | |
} | |
} | |
} | |
} | |
return nil | |
} | |
private func isMimeTypeConfigured(_ mimeType:String) -> Bool { | |
for record in self.mimeTypes { | |
if mimeType.contains(record.type) { | |
return true | |
} | |
} | |
return false | |
} | |
private func moveDownloadedFile(url:URL, fileName:String) -> URL { | |
let tempDir = NSTemporaryDirectory() | |
let destinationPath = tempDir + fileName | |
let destinationURL = URL(fileURLWithPath: destinationPath) | |
try? FileManager.default.removeItem(at: destinationURL) | |
try? FileManager.default.moveItem(at: url, to: destinationURL) | |
return destinationURL | |
} | |
} | |
extension WKWebviewDownloadHelper: WKNavigationDelegate { | |
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { | |
decisionHandler(.allow) | |
} | |
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) { | |
if let mimeType = navigationResponse.response.mimeType { | |
if isMimeTypeConfigured(mimeType) { | |
if let url = navigationResponse.response.url { | |
if #available(iOS 14.5, *) { | |
decisionHandler(.download) | |
} else { | |
var fileName = getDefaultFileName(forMimeType: mimeType) | |
if let name = getFileNameFromResponse(navigationResponse.response) { | |
fileName = name | |
} | |
downloadData(fromURL: url, fileName: fileName) { success, destinationURL in | |
if success, let destinationURL = destinationURL { | |
self.delegate.fileDownloadedAtURL(url: destinationURL) | |
} | |
} | |
decisionHandler(.cancel) | |
} | |
return | |
} | |
} | |
} | |
decisionHandler(.allow) | |
} | |
@available(iOS 14.5, *) | |
func webView(_ webView: WKWebView, navigationResponse: WKNavigationResponse, didBecome download: WKDownload) { | |
print(" navigationresponse didbecome download ") | |
download.delegate = self | |
} | |
} | |
@available(iOS 14.5, *) | |
extension WKWebviewDownloadHelper: WKDownloadDelegate { | |
func download(_ download: WKDownload, decideDestinationUsing response: URLResponse, suggestedFilename: String, completionHandler: @escaping (URL?) -> Void) { | |
let temporaryDir = NSTemporaryDirectory() | |
let fileName = temporaryDir + "/" + suggestedFilename | |
let url = URL(fileURLWithPath: fileName) | |
fileDestinationURL = url | |
completionHandler(url) | |
} | |
func download(_ download: WKDownload, didFailWithError error: Error, resumeData: Data?) { | |
print("download failed \(error)") | |
} | |
func downloadDidFinish(_ download: WKDownload) { | |
print("download finish") | |
if let url = fileDestinationURL { | |
self.delegate.fileDownloadedAtURL(url: url) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment