Search code examples
jqueryqtwebkitqtwebkitqwebview

Qt, how to simulate user clicks in input type=file


My question in short: I want to upload images to a website automatically. However, I couldn't simulate input type=file.

I have the following input element in a webpage.

<input id="fileupload" type="file" name="files[]" data-url="/server/images/e1b2d17b7b7eccef21a0a0ba1756d35c/upload/" multiple="">

I know that it is disabled due to security reasons to simulate this element using JS or JQuery. That's fine. However, I load the page into my QWebElement and I want to upload images automatically by simulating the necessary mouse clicks. I have managed to click to the upload button but I can't simulate typing any folder name or file name into the opened Dialog Box. I think I need to focus on the Dialog Box but couldn't do it. Could anyone guide me a bit?


Solution

  • You should send mouse click event to input point coordinates. Here is PyQt code to do it.

    # We need to scroll our window, to make input "visible" and get it's coordinates
    el_pos = el.geometry().center()  # el - QWebElement points to input
    self._page.mainFrame().setScrollPosition(el_pos)  # self._page - QWebPage
    scr_pos = self._page.mainFrame().scrollPosition()
    point_to_click = el_pos - scr_pos
    
    # Create click on coordinates
    press = QMouseEvent(QMouseEvent.MouseButtonPress, point_to_click, Qt.LeftButton, Qt.LeftButton, Qt.NoModifier)
    release = QMouseEvent(QMouseEvent.MouseButtonRelease, point_to_click, Qt.LeftButton, Qt.LeftButton, Qt.NoModifier)
    QApplication.postEvent(self._handler, press)  # self._handler - QWebView
    QApplication.postEvent(self._handler, release)
    

    After choose file dialog "opened", Qt calls QWebPage.chooseFile() function to get file name, that should be choosen. We need to reimplement this method in out QWebPage:

    class WebPage(QWebPage):
        def __init__(self):
            QWebPage.__init__(self)
            self.file_name = 'test.png'  # file name we want to be choosed
    
        def chooseFile(self, frame, suggested_file):
            return self.file_name  # file will be choosen after click on input type=file
    

    Update:

    And one more thing. In case input allow to select multiple files, reimplementing QWebPage.chooseFile() wouldn't work. To handle this, you should add support of QWebPage::ChooseMultipleFilesExtension. Here is simple example how to do it.