Search code examples
pythondownloadpyqtpyqt5pyqt6

Python PyQt6 QWebEngineView Multiple Downloads


I'm having trouble downloading multiple files through a QWebEngineView in PyQt6 on Python. I've tried a few different ways (opening the window twice, creating multiple views, etc.) but I can only ever get a maximum of one of the files downloaded.

Here is one example of my download window:

class DownloadFileWindow(QWidget):

    def __init__(self, fileNames: list, urls: list, saveFolder: str):

        super().__init__()

        hbox = QHBoxLayout(self)

        for i in range(len(fileNames)):

            view = QWebEngineView()

            view.page().profile().downloadRequested.connect(partial(self.onDownloadRequested, fileNames[i], saveFolder))

            view.load(QUrl(urls[i]))

            hbox.addWidget(view)

    def onDownloadRequested(self, fileName: str, saveFolder: str, download: QWebEngineDownloadRequest):

        download.setDownloadDirectory(saveFolder)
        download.setDownloadFileName(fileName)
        download.accept()

In the above example, only the first file in the list is downloaded, and I get the below messages in the console (not errors, the execution doesn't stop):

Setting the download directory is not allowed after the download has been accepted. Setting the download file name is not allowed after the download has been accepted.

So it looks like no matter what I try, it keeps trying to use the same download variable, even though I instantiate it for each file (at least I think I do).

I've tried:

  • opening the download window once for each URL
  • creating multiple views, one for each URL
  • waiting for each download to finish before starting the next one

but I get the same or similar problems where only the first file is downloaded.

I would expect that at least one of these methods allows me to download all of the files that I want, but no dice.


Solution

  • Thanks to @musicamante, I knew what I had to search for and found a solution on another SO post: Do multiple QWebEngineViews use the same web page cache profile

    As @musicamante said, the issue is that each QWebEngineView uses the same default QWebEngineProfile unless specified otherwise. A unique QWebEngineProfile for each QWebEngineView must be created along with a QWebEnginePage that uses that profile, then assign those to the QWebEngineView.

    Copied example from the other SO answer:

    from PyQt6.QtWebEngineCore import QWebEngineProfile, QWebEnginePage
    
    ...
    for i in range(3):
        storage = "unique/storage/location" + str(i)  # <- unique for each iteration
        webview = QWebEngineView()
        profile = QWebEngineProfile(storage, webview)
        page = QWebEnginePage(profile, webview)
        webview.setPage(page)
        webview.load(QUrl(url))
        ...
    
    ...