Input type=file not working in WebView of OS X application

前端 未结 1 511
忘了有多久
忘了有多久 2021-01-03 01:31

I have created an OSX application in Swift and embedded a WebView in it using Xcode 7. I have a file selector on the web page loaded by the WebView which asks the user to br

相关标签:
1条回答
  • 2021-01-03 01:59

    I have not worked with this myself, but from puzzling bits and pieces together this seems to do what you'd like.

    First...I'm using a WKWebView. That is declared and initialised with a local HTML file like so:

    import Cocoa
    import WebKit
    
    class ViewController: NSViewController {
    
        let webview: WKWebView = WKWebView()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            webview.autoresizingMask = [.viewWidthSizable, .viewHeightSizable]
            webview.frame = view.bounds
            webview.uiDelegate = self
            view.addSubview(webview)
    
            let fileURL = URL(fileURLWithPath: "/Users/myuserhere/Desktop/index.html")
            webview.loadFileURL(fileURL, allowingReadAccessTo: fileURL)
         }
      }
    

    The interesting part is webview.uiDelegate. This promises that we will conform to the WKUIDelegate protocol documented here. As it says:

    The WKUIDelegate class provides methods for presenting native user interface elements on behalf of a webpage.

    One of the methods you can implement is runOpenPanelWithParameters:

    If you implement this method, you promise that you will present a file upload panel and call the callback method of this method with the outcome of what the user selected. Remember to also call the callback method when the user presses cancel.

    Here is a quick and dirty example:

    extension ViewController: WKUIDelegate {
        func webView(_ webView: WKWebView, runOpenPanelWith parameters: WKOpenPanelParameters, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping ([URL]?) -> Void) {
            let openPanel = NSOpenPanel()
            openPanel.canChooseFiles = true
            openPanel.begin { (result) in
                if result == NSApplication.ModalResponse.OK {
                    if let url = openPanel.url {
                        completionHandler([url])
                    }
                } else if result == NSApplication.ModalResponse.cancel {
                    completionHandler(nil)
                }
            }
        }
    }
    

    Hopefully that gives you something to get started with.

    Bonus Material

    Here are some links that helped me:

    How to upload files from WKWebView

    How to implement the delegate method

    How to create a NSOpenPanel in Swift

    For iOS (asked by @DarshanMothreja)

    I tried gluing together a simple program to do the same on iOS. I hope it is useful to you @DarshanMothreja

    HTML A file called index.html is added to the Xcode project. The content looks like this:

    <!DOCTYPE html>
    <html lang="en" dir="ltr">
      <head>
        <meta charset="utf-8">
        <title>Test</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
      </head>
      <body>
        <label for="file">File goes here</label>
        <input type="file" name="file" value="File">
      </body>
    </html>

    Swift

    Here is the ViewController

    import UIKit
    import WebKit
    
    class ViewController: UIViewController {
        let webview: WKWebView = WKWebView()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            webview.autoresizingMask = [ .flexibleWidth, .flexibleHeight ]
            webview.frame = view.bounds
            webview.uiDelegate = self
            view.addSubview(webview)   
        
            if let path = Bundle.main.path(forResource: "index", ofType: "html") {
                let fileURL = URL(fileURLWithPath: path)
                webview.loadFileURL(fileURL, allowingReadAccessTo: fileURL)
            }
        }
    }
    
    extension ViewController: WKUIDelegate { }
    

    If I run the above, I get this result when I tap the "Choose File" button, no need to add any delegate methods.

    Hope that gives you something to work with.

    0 讨论(0)
提交回复
热议问题