我正在使用QTcpSocket通过HTTP在本地提供一些文件。我的问题是只有wget正确下载文件,firefox会在末尾添加四个额外的字节。这是我发送的标题:
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
我的问题是我做错了什么,为了做到这一点我应该改变什么?提前谢谢。
答案 0 :(得分:1)
您不应该用分号终止这些行。乍一看,这似乎是最可能的问题。
我对QDataStream(或一般的QT)了解不多,但是快速查看QDataStream文档提到了运算符&lt;&lt;(char const *)。如果您将一个以空字符结尾的字符串传递给QDataStream,那么您几乎肯定会越过最终缓冲区的末尾。
尝试使用QDataStream :: writeRawBytes()。
如果删除分号,则客户端应至少读取响应的正确字节数,并忽略最后四个字节。
我也忽略了“内容处理”。这是一个MIME事物,而不是HTTP事物。
答案 1 :(得分:1)
所以我找到了问题的整个解决方案,我认为有人可能需要它,所以这里是:
第一个问题是四个额外字节。这样做的原因是,根据QDataStream documentation,“写入流的每个项目都是以预定义的二进制格式编写的,这取决于项目的类型”。当QFile.readAll()
返回QByteArray
时,QDataStream.operator<<
按以下格式编写了该对象:
(link)
因此,四个额外字节是quint32的四个字节,表示数组大小。
根据janm的回答,解决方案是使用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,但这没有帮助。可能这是保持活力的事情,但老实说,只要它有效,我根本不关心:)。
答案 2 :(得分:0)
该行末尾不应有任何分号。