为啥 QNetworkReply readAll() 返回零字节?

Posted

技术标签:

【中文标题】为啥 QNetworkReply readAll() 返回零字节?【英文标题】:Why the QNetworkReply readAll() returns zero bytes?为什么 QNetworkReply readAll() 返回零字节? 【发布时间】:2011-08-21 07:22:30 【问题描述】:

我在pyqt4中使用qtwebkit通过QNetworkReply下载图片:

import os 
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import QWebPage

class dxBrowser(QWebPage):
def __init__(self,url):
    QWebPage.__init__(self)
    self._url=url
    self.manager=self.networkAccessManager()
    self.connect(self.manager,SIGNAL("finished(QNetworkReply *)"),self.onFinished)

def crawl(self):
    self.mainFrame().load(QUrl(self._url))

def onFinished(self,networkReply):
    if networkReply.rawHeader('Content-Type')=='image/png':
        print 'find the image'
        l=int(networkReply.rawHeader('Content-Length'))
        print l
        byteArray=networkReply.readAll()
        print byteArray.size()
        im=QImage.fromData(byteArray)
        if not im.save('test.jpg','jpg'):
            print 'image save error'


def main():
    app=QApplication(sys.argv)
    url='http://www.yiyaows.cn/DrsPath.do?kid=6666686E686E69673334333632303335&username=mylibddrz&spagenum=251&pages=50&fid=7534992&a=95cb07394dbf1d43c1fe61bdf6d4a36d&btime=2011-08-19&etime=2011-09-08&template=bookdsr1&firstdrs=http%3A%2F%2Fbook1.duxiu.com%2FbookDetail.jsp%3FdxNumber%3D000005609810%26d%3DA30222298F3C6715323B5476CB66D650'
    dx=dxBrowser(url)
    dx.crawl()
    sys.exit(app.exec_())

if __name__=='__main__':
    main()    

虽然内容长度不为零,但 byteArray.size() 为 0。所以我无法保存图像。为什么?谁能帮帮我。

编辑: 也许我想通了。 qtwebkit 可能已经检索到 qnetworkreply 的内容,一个 QIODevice,它的大小在 readall() 之后将为 0。我猜可能 qtwebkit 作为浏览器已经读取了它以进行渲染。

【问题讨论】:

dxBrowser 上的 reply 属性从何而来? 对不起,前面的代码有误。 【参考方案1】:

编辑:也许我想通了。 qtwebkit 可能已检索到 qnetworkreply 的内容,一个 QIODevice,它的大小为 0 在 readall() 之后。也许作为浏览器的 qtwebkit 已经阅读了它 渲染,我猜。

是的,有一个简单的解决方法:将QNetworkDiskCache 添加到管理器(使用QNetworkAccessManager.setCache)并从插槽onFinished 中的缓存中检索图像。

如果网站使用“Pragma: no-cache”或“Cache-control”来提示浏览器不要将文件保存到磁盘,你将不得不重新定义prepare(可能还有updateMetaData)的方法QNetworkDiskCache 在调用原始方法之前覆盖标志 saveToDisk

【讨论】:

设置缓存后,QNetworkAccessManager 实例是否自动写入该缓存?还是必须在每次请求后手动插入? @izyda 您只需调用setCache 一次,设置后立即对任何新请求起作用。 这很好,但现在我又回到了“Pragma: no-cache”或“Cache-control”问题。你能给我一些关于我应该如何处理这个问题的建议吗?我是否应该创建一个继承自 QNetworkDiskCache 并仅覆盖 prepare 方法的 Python 类?

以上是关于为啥 QNetworkReply readAll() 返回零字节?的主要内容,如果未能解决你的问题,请参考以下文章

Qt QNetworkReply readAll 在再次请求相同的 url 时返回空

从 QNetworkReply 读取未解码的数据

为啥在 Qtcpsocket 的 readyRead 回调中调用 readAll 时没有内容?

读取 HTTP 标头

为啥上传图片时收不到响应数据?

为啥qt不读取文件