【问题标题】:HTTP Content-Length incorrect size served?提供的 HTTP Content-Length 大小不正确?
【发布时间】:2010-08-09 12:49:12
【问题描述】:

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

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

【问题讨论】:

    标签: c++ http qt http-headers httpresponse


    【解决方案1】:

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

    我对 QDataStream(或一般的 QT)了解不多,但是快速浏览一下 QDataStream 文档会提到 operator

    尝试使用 QDataStream::writeRawBytes()。

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

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

    【讨论】:

    • 我删除了它们,但没有任何改变。
    • Content-Disposition 肯定是 HTTP 的一部分。 RFC2616,第 19.5.1 节。
    • @bobince:第 19.5 节是“附加功能”,讨论实现者应该注意但不依赖的事情。 RFC2616 的第 15.5 节说“Content-Disposition 不是 HTTP 标准的一部分,但由于它被广泛实施,我们正在为实施者记录它的使用和风险”
    • 在任何情况下,当试图让 Flash 插件显示 Flash 内容时,“附件”的内容配置是不正确的。
    • 这可能是故意的,以停止浏览器尝试内联显示文件,并提供下载。
    【解决方案2】:

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

    第一个问题是四个额外的字节。原因是根据QDataStream documentation,“写入流的每个项目都以预定义的二进制格式写入,该格式取决于项目的类型”。由于QFile.readAll() 返回了QByteArrayQDataStream.operator&lt;&lt; 以以下格式写入该对象:

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

    (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,但这并没有帮助。可能是keepalive的事情,但老实说,只要它有效,我根本不在乎:)。

    【讨论】:

      【解决方案3】:

      行尾不应有分号。

      【讨论】:

        猜你喜欢
        • 2014-06-05
        • 1970-01-01
        • 2016-12-29
        • 1970-01-01
        • 2015-03-05
        • 1970-01-01
        • 2015-04-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多