开发者

HTTP Content-Length incorrect size served?

开发者 https://www.devze.com 2023-01-10 15:29 出处:网络
I\'m serving some files locally via HTTP using QTcpSocket. My problem is that only wget downloads the file properly, firefox adds four extra bytes to the end. This is the header I send:

I'm serving some files locally via HTTP using QTcpSocket. My problem is that only wget downloads the file properly, firefox adds four extra bytes to the end. This is the header I send:

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

This is the code used to send the response:

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

        QString name = tokens[1].right(tokens[1].length() - 1);
        QString res开发者_如何学运维name = ":/" + 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;
        }

As I stated above, wget gets it right and downloads the file properly. The problem is that Firefox (and my target application, a Flash ActiveX instance) don't.

The four extra bytes are always the same: 4E E9 A5 F4

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

My question is what am I doing wrong, and what should I change to get it right? Thanks in advance.


You should not be terminating the lines with semicolons. At first glance this seems like the most likely problem.

I don't know much about QDataStream (or QT in general), however a quick look at the QDataStream documentation mentions operator<<(char const*). If you are passing a null terminated string to QDataStream, you are almost certainly going over the end of the final buffer.

Try using QDataStream::writeRawBytes().

If you remove the semicolons, then the clients should at least read the correct number of bytes for the response and ignore the last four bytes.

I'd leave out "Content-Disposition" too. That's a MIME thing, not an HTTP thing.


So I found the whole solution to the question, and I think someone might need it, so here it is:

The first problem were the four extra bytes. The reason for this is that according to the QDataStream documentation, "each item written to the stream is written in a predefined binary format that varies depending on the item's type". And as QFile.readAll() returned a QByteArray, QDataStream.operator<< wrote that object in the following format:

  • If the byte array is null: 0xFFFFFFFF (quint32)
  • Otherwise: the array size (quint32) followed by the array bytes, i.e. size bytes

(link)

So, the four extra bytes were the four bytes of quint32 that denoted the array size.

The solution, according to janm's answer was to use the writeRawBytes() function.

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

Wget probably got it right the first time because it strictly enforces the Content-Length field of the HTTP header, while apparently firefox does not.

The second problem was that despite the right header and working sockets, the flashplayer did not display the desired content at all. I experimented with various fields to make it work, and noticed that by uploading to a real server, it works all right. I copied the header from server, and tadaa! it works. This is the header:

  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

At first I only tried setting the version to 1.1, but that didn't help. Probably it's the keepalive thing, but honestly, I don't care at all as long as it works :).


There shouldn't be any semicolons at the end of the line.

0

精彩评论

暂无评论...
验证码 换一张
取 消