ZetCode

Dart HttpClient

最后修改于 2025 年 4 月 4 日

Dart 中的 HttpClient 类提供了一种强大的方式来发出 HTTP 请求。它支持各种 HTTP 方法、标头以及请求/响应处理。

HttpClient 是 Dart dart:io 库的一部分,适用于命令行和服务器应用程序。它不适用于浏览器环境。

基本定义

HttpClient 是用于发出 HTTP 请求的客户端。它支持 GET、POST、PUT、DELETE 以及其他具有可配置选项的 HTTP 方法。

主要功能包括连接持久化、Cookie 管理和请求配置。它提供了对请求的高级和低级控制。

基本的 GET 请求

此示例展示了如何发出简单的 GET 请求来获取数据。

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

void main() async {
  var client = HttpClient();
  
  try {
    var request = await client.getUrl(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));
    var response = await request.close();
    
    if (response.statusCode == HttpStatus.ok) {
      var json = await response.transform(utf8.decoder).join();
      print('Response data: $json');
    } else {
      print('Request failed with status: ${response.statusCode}');
    }
  } finally {
    client.close();
  }
}

我们创建一个 HttpClient 实例,发出一个 GET 请求,并处理响应。客户端在使用后必须关闭以释放资源。我们使用 async/await 进行异步操作。

$ dart main.dart
Response data: {
  "userId": 1,
  "id": 1,
  "title": "sunt aut facere...",
  "body": "quia et suscipit..."
}

带 JSON 的 POST 请求

此示例演示了如何使用 POST 请求发送 JSON 数据。

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

void main() async {
  var client = HttpClient();
  
  try {
    var request = await client.postUrl(
      Uri.parse('https://jsonplaceholder.typicode.com/posts'));
    
    request.headers.contentType = ContentType.json;
    request.write(jsonEncode({
      'title': 'foo',
      'body': 'bar',
      'userId': 1
    }));
    
    var response = await request.close();
    var responseBody = await response.transform(utf8.decoder).join();
    
    print('Response status: ${response.statusCode}');
    print('Response body: $responseBody');
  } finally {
    client.close();
  }
}

我们使用 JSON 内容类型配置 POST 请求,并发送编码后的 JSON 数据。服务器响应创建的资源,包括分配的 ID。标头在写入请求正文之前设置。

$ dart main.dart
Response status: 201
Response body: {
  "title": "foo",
  "body": "bar",
  "userId": 1,
  "id": 101
}

处理标头

此示例展示了如何设置请求标头和读取响应标头。

main.dart
import 'dart:io';

void main() async {
  var client = HttpClient();
  
  try {
    var request = await client.getUrl(
      Uri.parse('https://httpbin.org/headers'));
    
    // Set custom headers
    request.headers.add('X-Custom-Header', 'DartClient');
    request.headers.add('Accept', 'application/json');
    
    var response = await request.close();
    
    // Print response headers
    print('Response headers:');
    response.headers.forEach((name, values) {
      print('$name: $values');
    });
    
    // Print response body
    var body = await response.transform(utf8.decoder).join();
    print('\nResponse body:\n$body');
  } finally {
    client.close();
  }
}

我们将自定义标头添加到请求中,并检查响应标头。httpbin.org 服务在响应正文中回显我们的请求标头。标头值始终是列表,因为 HTTP 允许为每个标头设置多个值。

$ dart main.dart
Response headers:
date: [Wed, 03 Apr 2024 12:00:00 GMT]
content-type: [application/json]
...

Response body:
{
  "headers": {
    "Accept": "application/json",
    "Host": "httpbin.org",
    "X-Custom-Header": "DartClient",
    ...
  }
}

文件下载

此示例演示了如何下载文件并将其本地保存。

main.dart
import 'dart:io';

void main() async {
  var client = HttpClient();
  var file = File('downloaded_image.jpg');
  
  try {
    var request = await client.getUrl(
      Uri.parse('https://picsum.photos/200/300.jpg'));
    var response = await request.close();
    
    if (response.statusCode == HttpStatus.ok) {
      await response.pipe(file.openWrite());
      print('File downloaded successfully');
    } else {
      print('Download failed: ${response.statusCode}');
    }
  } finally {
    client.close();
  }
}

我们下载一个图片文件,并将其直接流式传输到本地文件。pipe() 方法高效地处理数据传输,而无需将整个文件加载到内存中。这种方法适用于大文件。

$ dart main.dart
File downloaded successfully

错误处理

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

main.dart
import 'dart:io';

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 Exception catch (e) {
    print('Unexpected error: $e');
  } finally {
    client.close();
  }
}

我们演示了如何捕获 HTTP 请求期间可能发生的特定异常。SocketException 处理网络问题,HttpException 捕获 HTTP 特定的错误。始终在 finally 块中关闭客户端。

$ dart main.dart
Network error: SocketException: Failed host lookup...

最佳实践

来源

Dart HttpClient 文档

本教程通过实际示例介绍了 Dart 的 HttpClient 类,展示了基本请求、标头、文件下载和错误处理。

作者

我的名字是 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有十多年的经验。

列出 所有 Dart 教程