0

我正在使用 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

十六进制转储 http://www.freeimagehosting.net/uploads/a5711fd7af.gif

我的问题是我做错了什么,我应该改变什么才能让它正确?提前致谢。

4

3 回答 3

1

您不应该用分号终止行。乍一看,这似乎是最有可能出现的问题。

我对 QDataStream(或一般的 QT)了解不多,但是快速浏览一下 QDataStream 文档会提到 operator<<(char const*)。如果您将一个以空结尾的字符串传递给 QDataStream,那么您几乎肯定会越过最终缓冲区的末尾。

尝试使用 QDataStream::writeRawBytes()。

如果删除分号,则客户端至少应读取响应的正确字节数并忽略最后四个字节。

我也会省略“内容处置”。这是 MIME 的事情,而不是 HTTP 的事情。

于 2010-08-09T12:59:02.113 回答
1

所以我找到了问题的完整解决方案,我认为有人可能需要它,所以这里是:

第一个问题是四个额外的字节。这样做的原因是,根据QDataStream 文档,“写入流的每个项目都以预定义的二进制格式写入,该格式取决于项目的类型”。并作为QFile.readAll()返回 a QByteArrayQDataStream.operator<<以以下格式编写该对象:

  • 如果字节数组为空:0xFFFFFFFF (quint32)
  • 否则:数组大小(quint32)后跟数组字节,即大小字节

链接

因此,四个额外的字节是 quint32 的四个字节,表示数组大小。

根据 janm 的回答,解决方案是使用该writeRawBytes()功能。

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

Wget 可能第一次就做对了,因为它严格执行Content-LengthHTTP 标头的字段,而 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,但这并没有帮助。可能是keepalive的事情,但老实说,只要它有效,我根本不在乎:)。

于 2010-08-11T13:22:44.770 回答
0

行尾不应有任何分号。

于 2010-08-09T12:59:02.847 回答