【问题标题】:Input type=file not working in WebView of OS X application输入类型=文件在 OS X 应用程序的 WebView 中不起作用
【发布时间】:2017-03-22 09:39:11
【问题描述】:

我在 Swift 中创建了一个 OSX 应用程序,并使用 Xcode 7 在其中嵌入了一个 WebView。我在 WebView 加载的网页上有一个文件选择器,它要求用户浏览用户计算机上的特定文件。我面临的问题是当用户点击浏览按钮时没有任何反应。

如果我在 Safari 中打开相同的网页,相同的文件选择器控件可以正常工作。

我在 swift 方面相对较新,因此我们将不胜感激。

这是我的viewDidLoad 函数:

func viewDidLoad() {
    super.viewDidLoad() 
    let url=NSURL(string: "http://video.online-convert.com/convert-to-mp4")
    let request=NSURLRequest(URL:url!) 
    webView.frameLoadDelegate=self 
    webView.mainFrame.loadRequest(request)  
    webView.shouldCloseWithWindow = true 
    webView.drawsBackground = true 
}

谢谢。

【问题讨论】:

  • 这可能与 URL 对象的创建方式有关,但您能否向我们展示一些您的代码。它使我们更容易查明问题:)
  • "video.online-convert.com/convert-to-mp4" 不是本地html页面的路径吗?
  • 但是如果我理解正确的话,您想在 web 视图中打开一个 local html 页面(位于您自己机器上的页面)对吧?还是我误解了你的问题?
  • 是的,你是对的。我的项目是打开一个驻留在我的计算机中的本地 html 页面。本地 html 页面中有一个浏览文件按钮,它允许用户从他的本地计算机中选择一个文本文件进行一些处理。但是,当我的浏览文件按钮不起作用时,我尝试使用外部站点来查看错误是在我的页面中还是在 WebView 中。结果是一样的。输入类型=文件元素在 WebVew 中没有响应。可能是什么原因?

标签: swift macos file webview selector


【解决方案1】:

我自己没有处理过这个,但是从令人费解的点点滴滴看来,这似乎可以满足您的需求。

首先...我使用的是WKWebView。这是使用本地 HTML 文件声明和初始化的,如下所示:

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)
     }
  }

有趣的部分是webview.uiDelegate。这保证我们将遵守WKUIDelegate 协议documented here。正如它所说:

WKUIDelegate 类提供了代表网页呈现本地用户界面元素的方法。

您可以实现的方法之一是runOpenPanelWithParameters:

如果您实施此方法,您承诺您将展示一个文件上传面板并调用此方法的callback 方法,并返回用户选择的结果。 记住在用户按下cancel时也要调用callback方法。

这是一个快速而肮脏的例子:

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)
            }
        }
    }
}

希望这能给你一些入门的东西。

奖励材料

以下是一些对我有帮助的链接:

How to upload files from WKWebView

How to implement the delegate method

How to create a NSOpenPanel in Swift

对于 iOS(@DarshanMothreja 询问)

我尝试将一个简单的程序粘合在一起,以便在 iOS 上执行相同的操作。我希望它对你有用@DarshanMothreja

HTML 一个名为index.html 的文件被添加到Xcode 项目中。内容如下:

<!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>

斯威夫特

这里是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 { }

如果我运行上面的,当我点击“选择文件”按钮时,我会得到这个结果,不需要添加任何委托方法。

希望能给你一些工作。

【讨论】:

  • 你能推荐iOS吗
  • @DarshanMothreja 也许 :) 你想达到什么目的?
  • @Heitor 谢谢,很高兴它帮助了你。我想你在iOS上有这个问题吗?我没有任何明显的建议/解决方案,但也许看看取消是什么......我的意思是,您是否需要重新加载取消页面。对不起,这是我现在能想到的最好的了
  • 这是 MacOS。我正在寻找 Swift 方面的解决方案,而不是 html/js 方面...错误的取消按钮在上传窗口中,我想谁不是 js。
  • @Heitor 好的,我又看了一遍。如果您按下openPanel 中的取消按钮,您可以在控制台[NSVBSavePanel observeValueForKeyPath:ofObject:change:context:] caught non-fatal NSInternalInconsistencyException 'Completion handler passed to -[WebTest.ViewController webView:runOpenPanelWithParameters:initiatedByFrame:completionHandler:] was not called' with backtrace 中看到此错误。这意味着当 openDialog 被解除时回调没有被调用。所以我们也必须检查这种情况。我已经更新了我的答案,寻找NSApplication.ModalResponse.cancel 部分
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-09
  • 1970-01-01
  • 2017-08-28
  • 1970-01-01
  • 2023-03-10
相关资源
最近更新 更多