2010-08-09 97 views
0

我使用QTcpSocket通过HTTP在本地提供一些文件。我的问题是,只有wget正确下载文件,firefox会在最后添加四个额外的字节。这是我送的标题:服务HTTP内容长度不正确?

HTTP/1.0 200 Ok 
    Content-Length: 382917; 
    Content-Type: application/x-shockwave-flash; 
    Content-Disposition: attachment; filename=file.swf; 

这是用来发送响应代码:

 QTextStream os(socket); 
     os.setAutoDetectUnicode(true); 

     QString name = tokens[1].right(tokens[1].length() - 1); 
     QString resname = ":/" + name; // the served file is a Qt resource 
     QFile f(resname); f.open(QIODevice::ReadOnly); 

     os << "HTTP/1.0 200 Ok\r\n" << 
       "Content-Length: " << f.size() << ";\r\n" << 
       "Content-Type: application/x-shockwave-flash;\r\n" << 
       "Content-Disposition: attachment; filename=" << name << 
       ";\r\n\r\n"; 

     os.flush(); 

     QDataStream ds(socket); 

     ds << f.readAll(); 

     socket->close(); 

     if (socket->state() == QTcpSocket::UnconnectedState) 
     { 
      delete socket; 
     } 

正如我上文所述,wget的得到它的权利和正确下载文件。问题是Firefox(和我的目标应用程序,一个Flash ActiveX实例)没有。

四个额外的字节都是一样的:4E E9 A5 F4

Hex dump http://www.freeimagehosting.net/uploads/a5711fd7af.gif

我的问题是我在做什么错了,我应该怎么改得到它吗?提前致谢。

回答

1

你不应该用分号终止行。乍一看这似乎是最可能的问题。

我对QDataStream(或一般的QT)并不了解,但快速查看QDataStream文档中提到的操作符< <(char const *)。如果你将一个以null结尾的字符串传递给QDataStream,你几乎肯定会遍历最后一个缓冲区的末尾。

尝试使用QDataStream :: writeRawBytes()。

如果您删除分号,则客户端应至少读取响应的正确字节数,并忽略最后四个字节。我也不知道“Content-Disposition”。这是一个MIME的东西,而不是HTTP的东西。

+0

我删除了它们,但没有更改。 – 2010-08-09 13:08:16

+0

'Content-Disposition'肯定是HTTP的一部分。 RFC2616,第19.5.1节。 – bobince 2010-08-09 13:57:21

+0

@bobince:第19.5节是“附加功能”,讨论实现者应该意识到但不依赖于的东西。 RFC2616的第15.5节说:“内容处置不是HTTP 标准的一部分,但由于它被广泛实施,我们正在记录其实施者使用和风险” – janm 2010-08-09 14:19:58

0

该行末尾不应该有分号。

1

所以我觉得整个解决问题,我觉得有人可能需要它,所以这里是:

的第一个问题是四个额外的字节。原因是根据QDataStream documentation,“写入流中的每个项目都是以预定义的二进制格式写入的,这取决于项目的类型”。和作为QFile.readAll()返回QByteArrayQDataStream.operator<<写道,以下列格式对象:否则为0xFFFFFFFF(quint32)

  • :遵循的阵列大小(quint32)由阵列的字节,

    • 如果字节数组为空即size个字节

    link

    所以,这四个额外的字节是那个表示的阵列尺寸的四个字节quint32的。

    根据詹姆的回答,解决方案是使用writeRawBytes()函数。

    QDataStream ds(socket); 
    ds.writeRawData(f.readAll().data(), f.size()); 
    

    Wget的可能得到正确的第一时间,因为它严格执行HTTP标头的Content-Length领域,而显然Firefox没有。

    第二个问题是尽管有正确的标题和工作套接字,Flashplayer根本没有显示所需的内容。我尝试了各个领域的工作,并注意到通过上传到真实的服务器,它可以正常工作。我从服务器复制标题,然后tadaa!有用。这是标题:

    HTTP/1.1 200 OK 
        Server: Apache/2.2.15 (Fedora) 
        Accept-Ranges: bytes 
        Content-Length: 382917 
        Content-Type: application/x-shockwave-flash 
        Keep-Alive: timeout=15, max=100 
        Connection: Keep-Alive 
    

    起初我只是试图设置版本为1.1,但没有帮助。可能它是保持活力的东西,但说实话,只要它工作,我都不在乎:)。