ZetCode

Dart HttpClientResponse

最后修改于 2025 年 4 月 4 日

Dart 中的 HttpClientResponse 类表示 HTTP 请求的响应。它提供了对响应头、状态码和响应体的访问。

HttpClientResponse 是一个字节数据流,必须完全读取或取消。它是 Dart dart:io 库的一部分,用于服务器端应用程序。

基本定义

HttpClientResponse 是一个抽象类,它实现了 Stream<List<int>>。它提供了 HTTP 特定的响应信息和作为流的响应体。

关键属性包括 statusCode、headers、contentLength 和 compressionState。必须消耗响应体以正确释放系统资源。

基本 HTTP GET 请求

本示例展示了如何进行简单的 GET 请求并读取响应。

main.dart
import 'dart:io';
import 'dart:convert';

Future<void> main() async {
  var client = HttpClient();
  
  try {
    var request = await client.getUrl(Uri.parse('https://example.com'));
    var response = await request.close();
    
    print('Status code: ${response.statusCode}');
    print('Headers: ${response.headers}');
    
    var body = await response.transform(utf8.decoder).join();
    print('Body length: ${body.length}');
  } finally {
    client.close();
  }
}

我们创建一个 HttpClient,发出一个 GET 请求,并处理响应。响应体被读取为 UTF-8 字符串。完成后务必关闭客户端。

$ dart main.dart
Status code: 200
Headers: {content-encoding: gzip, accept-ranges: bytes, ...}
Body length: 1256

处理响应标头

本示例演示了访问和使用响应头。

main.dart
import 'dart:io';

Future<void> main() async {
  var client = HttpClient();
  
  try {
    var request = await client.getUrl(Uri.parse('https://example.com'));
    var response = await request.close();
    
    print('Content-Type: ${response.headers.contentType}');
    print('Content-Length: ${response.contentLength}');
    print('Last-Modified: ${response.headers.value('last-modified')}');
    
    response.headers.forEach((name, values) {
      print('$name: $values');
    });
  } finally {
    client.close();
  }
}

我们通过方便的属性访问常用头,并遍历所有头。头是大小写不敏感的,并且可能具有多个值。

$ dart main.dart
Content-Type: text/html; charset=UTF-8
Content-Length: 648
Last-Modified: null
content-encoding: [gzip]
accept-ranges: [bytes]
...

将响应读取为 JSON

本示例展示了如何解析 API 的 JSON 响应。

main.dart
import 'dart:io';
import 'dart:convert';

Future<void> main() async {
  var client = HttpClient();
  
  try {
    var request = await client.getUrl(
      Uri.parse('https://jsonplaceholder.typicode.com/todos/1')
    );
    var response = await request.close();
    
    if (response.statusCode == 200) {
      var jsonString = await response.transform(utf8.decoder).join();
      var json = jsonDecode(jsonString);
      
      print('Todo ID: ${json['id']}');
      print('Title: ${json['title']}');
      print('Completed: ${json['completed']}');
    } else {
      print('Request failed with status: ${response.statusCode}');
    }
  } finally {
    client.close();
  }
}

我们获取一个 JSON 资源,解码响应体,并访问解析后的数据。在 JSON 解析之前,将响应流转换为 UTF-8。

$ dart main.dart
Todo ID: 1
Title: delectus aut autem
Completed: false

处理大型响应

本示例演示了分块流式传输大型响应。

main.dart
import 'dart:io';
import 'dart:convert';

Future<void> main() async {
  var client = HttpClient();
  
  try {
    var request = await client.getUrl(
      Uri.parse('https://example.com/large-file')
    );
    var response = await request.close();
    
    var file = File('large_file.txt').openWrite();
    var byteCount = 0;
    
    await response.listen((List<int> chunk) {
      byteCount += chunk.length;
      file.add(chunk);
      print('Received ${chunk.length} bytes (total: $byteCount)');
    }).asFuture();
    
    await file.close();
    print('File saved with $byteCount bytes');
  } finally {
    client.close();
  }
}

我们将大型响应直接流式传输到文件,而无需将其全部加载到内存中。listen() 方法处理从服务器到达的每个块。

$ dart main.dart
Received 16384 bytes (total: 16384)
Received 16384 bytes (total: 32768)
...
File saved with 5242880 bytes

错误处理

本示例展示了 HTTP 请求的正确错误处理。

main.dart
import 'dart:io';
import 'dart:convert';

Future<void> main() async {
  var client = HttpClient();
  
  try {
    var request = await client.getUrl(
      Uri.parse('https://nonexistent.example.com')
    );
    var response = await request.close();
    
    var body = await response.transform(utf8.decoder).join();
    print(body);
  } on SocketException catch (e) {
    print('Network error: $e');
  } on HttpException catch (e) {
    print('HTTP error: $e');
  } on FormatException catch (e) {
    print('Format error: $e');
  } finally {
    client.close();
  }
}

我们处理 HTTP 请求期间可能发生的各种类型的异常。SocketException 涵盖网络问题,HttpException 涵盖 HTTP 错误。

$ dart main.dart
Network error: SocketException: Failed host lookup: 'nonexistent.example.com'

最佳实践

来源

Dart HttpClientResponse 文档

本教程涵盖了 Dart 的 HttpClientResponse 类,并提供了实际示例,展示了响应处理、流式传输、错误管理和最佳实践。

作者

我叫 Jan Bodnar,是一名充满热情的程序员,拥有丰富的编程经验。我自 2007 年起撰写编程文章。至今,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出 所有 Dart 教程