HttpClient
HttpClient 是 Dart 中自带的 HTTP 库。不过 HttpClient 在 Flutter 中用的比较少,这里只简单介绍一下它的用法,代码示例如下:
scss
//创建一个HttpClient
HttpClient httpClient = HttpClient();
//打开Http连接
HttpClientRequest request = await httpClient.getUrl(
Uri.parse("https://www.baidu.com"),
);
//使用iPhone的UA
request.headers.add(
"user-agent",
"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1",
);
//等待连接服务器(会将请求信息发送给服务器)
HttpClientResponse response = await request.close();
//读取响应内容
_text = await response.transform(utf8.decoder).join();
//输出响应头
print(response.headers);
//关闭client后,通过该client发起的所有请求都会终止。
httpClient.close();
http 库
http 库是 Flutter 官方推荐使用的。首先我们需要引入 http 库。如下所示,在 pubspec.yaml 文件中声明依赖。
yaml
dependencies:
http: ^0.12.1
然后在代码中导入对应的包名,如下所示:
arduino
import 'package:http/http.dart';
http 的使用示例如下所示:
- get 请求
ini
var client = http.Client();
var uri = Uri.parse('https://www.ptpress.com.cn/');
Map<String, String> header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0)
Gecko / 20100101 Firefox / 70.0',
};
http.Response response = await client.get(uri, headers: header);
print(utf8.decode(response.bodyBytes));
client.close();
- post 请求
dart
var client = http.Client();
Map<String, String> bodyMap = {
'username': 'username',
'password': 'password'
};
Map<String, String> headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0)
Gecko / 20100101 Firefox / 70.0",
};
http.Response response = await
client.post('https://www.ptpress.com.cn/',
headers: headers, body: bodyMap);
print(utf8.decode(response.bodyBytes));
client.close();
Json 解析
我们可以在 Android studio 中下载 JsonToDart
插件,通过这个插件我们可以把 Json 转化为 Dart 类。如下图所示:
生成对应的文件后,我们就可以使用生成的 Person.fromJson
来生成对应的 model 对象了。代码示例如下:
dart
import 'dart:convert';
import 'package:http/http.dart' as http;
Future<Person> fetchPerson() async {
final response = await http.get(Uri.parse('https://api.example.com/user/1'));
if (response.statusCode == 200) {
return Person.fromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to load user');
}
}
dio 库
dio库是Flutter中常用的三方HTTP库。要使用 dio 库,需要添加如下依赖:
yaml
dependencies:
dio: ^3.0.9
- dio库的Get请求
dart
try{
Dio dio=new Dio();
dio.options.headers={
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101
Firefox/70.0"
};
Map<String,dynamic> queryParameters={
'id':'123456',
'book':'flutter'
};
Response response=await dio.get("https://www.ptpress.com.cn/",queryParameters:
queryParameters);
print(response);
}catch(e){
print(e);
}
- dio库的Post请求
dart
_dio_post() async{
try{
Dio dio=new Dio();
dio.options.headers={
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101
Firefox/70.0"
};
Map<String,dynamic> data={
'username':'username',
'password':'password'
};
Response response=await dio.post("https://www.ptpress.com.cn/",data: data);
print(response);
}catch(e){
print(e);
}
}
- dio库下载图片
scss
_dio_download() async{
var sdDir = await getExternalStorageDirectory();
Response response=await
Dio().download('https://cdn.ptpress.cn/pubcloud/null/
cover/2021051442E8BF9.jpg', sdDir.path+'/image.jpg');
}
- 使用dio库的FormData类上传多个文件
ini
_dio_formData_uploadFile(File image1, File file2, File file3) async {
Dio dio = new Dio();
String path1 = image1.path;
var name = path1.substring(path1.lastIndexOf("/") + 1, path1.length);
String path2 = file2.path;
var name2 = path1.substring(path2.lastIndexOf("/") + 1, path2.length);
String path3 = file3.path;
var name3 = path1.substring(path3.lastIndexOf("/") + 1, path3.length);
Map<String, dynamic> fileMap = {
"image1": await MultipartFile.fromFile(path1, filename: name),
// 支持文件数组上传
"files": [
await MultipartFile.fromFile(path2, filename: name2),
await MultipartFile.fromFile(path3, filename: name3),
],
};
FormData formData = new FormData.fromMap(fileMap);
Response response = await dio.post("http://127.0.0.1/info", data: formData);
}
- 分片下载
scss
Future downloadWithChunks(
url,
savePath, {
ProgressCallback onReceiveProgress,
}) async {
const firstChunkSize = 102;
const maxChunk = 3;
int total = 0;
var dio = Dio();
var progress = <int>[];
createCallback(no) {
return (int received, _) {
progress[no] = received;
if (onReceiveProgress != null && total != 0) {
onReceiveProgress(progress.reduce((a, b) => a + b), total);
}
};
}
Future<Response> downloadChunk(url, start, end, no) async {
progress.add(0);
--end;
return dio.download(
url,
savePath + "temp$no",
onReceiveProgress: createCallback(no),
options: Options(
headers: {"range": "bytes=$start-$end"},
),
);
}
Future mergeTempFiles(chunk) async {
File f = File(savePath + "temp0");
IOSink ioSink= f.openWrite(mode: FileMode.writeOnlyAppend);
for (int i = 1; i < chunk; ++i) {
File _f = File(savePath + "temp$i");
await ioSink.addStream(_f.openRead());
await _f.delete();
}
await ioSink.close();
await f.rename(savePath);
}
Response response = await downloadChunk(url, 0, firstChunkSize, 0);
if (response.statusCode == 206) {
total = int.parse(
response.headers.value(HttpHeaders.contentRangeHeader).split("/").last);
int reserved = total -
int.parse(response.headers.value(HttpHeaders.contentLengthHeader));
int chunk = (reserved / firstChunkSize).ceil() + 1;
if (chunk > 1) {
int chunkSize = firstChunkSize;
if (chunk > maxChunk + 1) {
chunk = maxChunk + 1;
chunkSize = (reserved / maxChunk).ceil();
}
var futures = <Future>[];
for (int i = 0; i < maxChunk; ++i) {
int start = firstChunkSize + i * chunkSize;
futures.add(downloadChunk(url, start, start + chunkSize, i + 1));
}
await Future.wait(futures);
}
await mergeTempFiles(chunk);
}
}