如何等待通过QNetworkAccessManager完成两次异步下载?

如何解决如何等待通过QNetworkAccessManager完成两次异步下载?

===摘要============================================

我使用QNetworkAccessManager和qnetworkrequests同时下载两个图像。我如何确定两次下载已完成?

===详细说明=============================

我有两个图像的URL,我想异步下载它们。为此,我初始化QNetworkAccessManager并使用两个qnetworkrequests。完成后,每个请求都将图像内容写入文件

问题是,两个请求彼此都不知道,因此,无法验证另一个请求是否已完成

您能否告诉我我如何等待两个请求完成

这是完整的代码

import sys

from PyQt5.QtCore import QUrl,QFile,qiodevice
from PyQt5.QtNetwork import QNetworkAccessManager,qnetworkrequest
from PyQt5.QtWidgets import QApplication,QWidget


class MainWindow(QWidget):
    def __init__(self):
        super(MainWindow,self).__init__()

        img_url1 = "https://somesite.com/image1.jpg"
        img_url2 = "https://somesite.com/image2.jpg"

        self.downloader = QNetworkAccessManager()

        self.requests = []
        self.temp_files = []

        for index,mediafile_url in enumerate([img_url1,img_url2]):
            self.requests.append(self.downloader.get(qnetworkrequest(QUrl(mediafile_url))))
            request = self.requests[index]

            self.temp_files.append(QFile(f'{mediafile_url.split("/")[-1]}'))
            temp_file = self.temp_files[index]

            request.finished.connect(lambda *args,r=request,tf=temp_file: self.download_image(r,tf))

        self.show()

    @staticmethod
    def download_image(request,temp_file):
        image_data = request.readAll()
        temp_file.open(qiodevice.writeonly)
        temp_file.write(image_data)
        temp_file.close()


app = QApplication(sys.argv)
window = MainWindow()
app.exec_()

解决方法

您必须创建一个跟踪下载的类:

from dataclasses import dataclass
import sys

from PyQt5.QtCore import pyqtSignal,QObject,QUrl,QFile,QIODevice
from PyQt5.QtNetwork import QNetworkAccessManager,QNetworkRequest,QNetworkReply
from PyQt5.QtWidgets import QApplication,QWidget


@dataclass
class DownloadRequest:
    url: QUrl
    filename: str


class DownloadManager(QObject):
    finished = pyqtSignal()

    def __init__(self,parent=None):
        super().__init__(parent)
        self._manager = QNetworkAccessManager()
        self._pending_downloads = 0

        self.manager.finished.connect(self.handle_finished)

    @property
    def manager(self):
        return self._manager

    @property
    def pending_downloads(self):
        return self._pending_downloads

    def download(self,requests):
        for request in requests:
            qrequest = QNetworkRequest(request.url)
            qrequest.setAttribute(QNetworkRequest.User,request.filename)
            self.manager.get(qrequest)
            self._pending_downloads += 1

    def handle_finished(self,reply):
        self._pending_downloads -= 1
        if reply.error() != QNetworkReply.NoError:
            print(f"code: {reply.error()} message: {reply.errorString()}")
        else:
            print("successful")
            filename = reply.attribute(QNetworkRequest.User)
            file = QFile(filename)
            if file.open(QIODevice.WriteOnly):
                file.write(reply.readAll())

        print(f"pending downloads {self.pending_downloads}")
        if self.pending_downloads == 0:
            self.finished.emit()


class MainWindow(QWidget):
    def __init__(self,parent=None):
        super().__init__(parent)

        self._manager = DownloadManager()
        self._manager.finished.connect(self.handle_finished)

        img_url1 = "https://docs.python.org/3/_static/py.png"
        img_url2 = "https://somesite.com/image2.jpg"

        request1 = DownloadRequest(QUrl(img_url1),img_url1.split("/")[-1])
        request2 = DownloadRequest(QUrl(img_url2),img_url2.split("/")[-1])

        self._manager.download([request1,request2])

    def handle_finished(self):
        print("finished")


def main():
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    app.exec_()


if __name__ == "__main__":
    main()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?