2

我正在尝试 gzip 一个 .html 文件,然后将其通过管道传输到HttpResponse.

import 'dart:io';

void main() {
  File f = new File('some_template.html');
  HttpServer.bind('localhost', 8080)
    .then((HttpServer server) {
      server.listen((HttpRequest request) {
        HttpResponse response = request.response;
        f.openRead()
          .transform(GZIP.encoder)
          .pipe(response);
      });
    });
}

没有错误,但是浏览器没有提供 html 页面,而是下载了压缩的 html 页面。愿意给我一个提示吗?

4

3 回答 3

5

如果客户端接受压缩数据并且满足其他一些要求(见下文),HttpServer 会自动将数据压缩为 GZIP。即使没有,您也不能只是压缩数据并期望浏览器能够理解它。浏览器需要纯文本 (HTML),并且可能只是将二进制数据下载到磁盘。您还需要设置标头的内容编码。

dart:io自动压缩数据,以下情况除外:

  • Content-Length已设置:Content-Lengthheader 必须是GZIPdart:io的长度,因此不能压缩数据,
  • 客户不接受(发送Accept-Encoding),或
  • Content-Encoding头已由开发人员设置。

Dart 的 http 实现的一些相关部分:

// _writeHeaders (http_impl.dart):
if (acceptEncodings != null &&
    acceptEncodings
        .expand((list) => list.split(","))
        .any((encoding) => encoding.trim().toLowerCase() == "gzip") &&
    contentEncoding == null) {
  headers.set(HttpHeaders.CONTENT_ENCODING, "gzip");
  _asGZip = true;
}

// _addStream (same file):
if (_asGZip) {
  stream = stream.transform(GZIP.encoder);
}
于 2013-09-07T15:13:24.587 回答
3

如上所述,如果设置Content-Length标题,则无法使用自动压缩。如果要设置Content-Length标头,它必须是压缩后的内容长度。

以下代码说明了如何使用压缩数据的内容长度来提供已压缩的资源。

import 'dart:convert';
import 'dart:io';

var page =
r'''
<html>
  <head>
    <title>Hello, world!!!</title>
  </head>
  <body>
    <h1>Hello, world!!!</h1>
  </body>
</html>
''';

void requestHandler(HttpRequest request) {
  List<int> compressed = GZIP.encode(UTF8.encode(page));
  request.response
    ..headers.contentType = ContentType.HTML
    ..headers.set(HttpHeaders.CONTENT_ENCODING, 'gzip')
    ..headers.contentLength = compressed.length
    ..add(compressed)
    ..close();
}

main() async {
  var server = await HttpServer.bind(InternetAddress.ANY_IP_V4, 8080);
  server.autoCompress = true;
  server.defaultResponseHeaders.chunkedTransferEncoding = true;
  server.listen(requestHandler);
}
于 2015-05-02T00:04:03.463 回答
2

在最新的 SDK 中,您必须启用HttpServer.autoCompressHttpHeaders.chunkedTransferEncoding

例子,

import "dart:io";

void main() {
  HttpServer
  .bind(InternetAddress.ANY_IP_V4, 8080)
  .then((server) {
    server.autoCompress = true;
    server.listen((HttpRequest request) {
      request.response.write('Hello, world!');
      request.response.close();
    });
  });
}

以下是响应标头:

content-encoding:gzip
content-type:text/plain; charset=utf-8
transfer-encoding:chunked
x-content-type-options:nosniff
x-frame-options:SAMEORIGIN
x-xss-protection:1; mode=block

请注意,如果是 HTTP/1.1,则会自动设置 chunckedTransferEncoding。

于 2014-10-21T14:47:19.477 回答