0

QTcpSocketを使用してHTTP経由でローカルにいくつかのファイルを提供しています。私の問題は、wgetだけがファイルを正しくダウンロードし、firefoxが最後に4バイトを追加することです。これは私が送信するヘッダーです:

  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インスタンス)がそうではないことです。

余分な4バイトは常に同じです。4E E9 A5 F4

16進ダンプhttp://www.freeimagehosting.net/uploads/a5711fd7af.gif

私の質問は、私が間違っていること、そしてそれを正しくするために何を変えるべきかということです。前もって感謝します。

4

3 に答える 3

1

行をセミコロンで終わらせないでください。一見すると、これが最も可能性の高い問題のように思えます。

QDataStream (または一般的な QT) についてはあまり知りませんが、QDataStream のドキュメントをざっと見てみると、operator<<(char const*) について言及されています。null で終了する文字列を QDataStream に渡す場合、ほぼ確実に最終バッファの末尾を超えています。

QDataStream::writeRawBytes() を使用してみてください。

セミコロンを削除すると、クライアントは少なくとも応答の正しいバイト数を読み取り、最後の 4 バイトを無視する必要があります。

「Content-Disposition」も省略します。これは MIME の問題であり、HTTP の問題ではありません。

于 2010-08-09T12:59:02.113 に答える
1

だから私は質問に対する全体の解決策を見つけました、そして私は誰かがそれを必要とするかもしれないと思うので、ここにあります:

最初の問題は、余分な 4 バイトでした。この理由は、QDataStream のドキュメントによると、「ストリームに書き込まれる各アイテムは、アイテムのタイプによって異なる事前定義されたバイナリ形式で書き込まれる」ためです。そしてQFile.readAll()返された aとして、そのオブジェクトを次の形式で書きましたQByteArray:QDataStream.operator<<

  • バイト配列が null の場合: 0xFFFFFFFF (quint32)
  • それ以外の場合: 配列サイズ (quint32) の後に配列バイト、つまり size バイト

(リンク)

したがって、余分な 4 バイトは、配列サイズを示す quint32 の 4 バイトでした。

janmの答えによると、解決策はwriteRawBytes()関数を使用することでした。

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

Content-LengthWgetは、HTTP ヘッダーのフィールドを厳密に適用するため、おそらく最初はうまくいきましたが、Firefox は明らかにそうではありません。

2 つ目の問題は、適切なヘッダーと動作しているソケットにもかかわらず、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 に設定しようとしただけでしたが、それは役に立ちませんでした。おそらくそれはキープアライブの問題ですが、正直なところ、それが機能する限り、私はまったく気にしません:)。

于 2010-08-11T13:22:44.770 に答える
0

行末にセミコロンがあってはなりません。

于 2010-08-09T12:59:02.847 に答える