- 推薦下我寫的一個http庫ajanuw_http
最基本的獲取數據
import 'package:http/http.dart' as http;
main(List<String> args) async {
var url = Uri.http('localhost:5000', '/test');
var r = await http.get(url);
print(r.body); // hello world
print(r.statusCode); // 服務器返回的狀態碼200
}
服務器拋出錯誤
import 'package:http/http.dart' as http;
main(List<String> args) async {
var url = Uri.http('localhost:5000', '/test');
var r = await http.get(url);
print(r.body); // {"statusCode":500,"error":"Internal Server Error","message":"服務器錯誤"}
print(r.statusCode); // 500
}
抓取請求錯誤
try {
var r = await http.get('http://closeExample.com');
print(r.statusCode);
} on SocketException catch (e) {
print(e); // SocketException: Failed host lookup: 'closeexample.com' (OS Error: No address associated with hostname, errno = 7)
}
在指定的時間中斷請求
import 'package:http/http.dart' as http;
main(List<String> args) async {
var client = http.Client();
Future.delayed(Duration(seconds: 5)).then((_) {
print('關閉這個請求');
client.close();
});
try {
var url = Uri.http('localhost:5000', '/test');
print('請求開始');
var r = await client.get(url);
print(r.body);
print(r.statusCode);
} on http.ClientException catch(e) {
/// 捕獲中斷后拋出的錯誤
print(e);
} catch (e) {
print('Other Error: $e');
}
}
@Get('test')
async getHello(): Promise<string> {
//延遲 10s后發出數據
return await new Promise(res => {
setTimeout(() => {
res('hello world');
}, 10000);
});
}
打印結果
$ dart ./bin/main.dart
請求開始
關閉這個請求
Connection closed before full header was received
發送文件到服務器
客服端:
import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:http/http.dart';
String __filename = Platform.script.path.replaceFirst('/', '');
String __dirname = path.dirname(__filename);
main(List<String> arguments) async {
var uri = Uri.parse("http://localhost:3000/upload");
MultipartRequest request = MultipartRequest("POST", uri);
request.fields['user'] = 'Ajanuw';
request.files.add(
await MultipartFile.fromPath('file', path.join(__dirname, 'test.jpg')),
);
var r = await request.send();
print(r.statusCode);
print(await r.stream.bytesToString());
}
服務器端代碼片段:
@Post('upload')
@UseInterceptors(FileInterceptor('file'))
UploadedFile(@UploadedFile() file, @Body() body) {
console.log(file);
console.log(body);
const writeImage = createWriteStream(
join(__dirname, '..', 'upload', `${file.originalname}`),
);
writeImage.write(file.buffer);
return 'ok';
}
執行客服端代碼:
λ dart ./bin/main.dart
201
ok
服務端打印:
[0] { fieldname: 'file',
[0] originalname: 'test.jpg',
[0] encoding: '7bit',
[0] mimetype: 'application/octet-stream',
[0] buffer:
[0] <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 00 01 00 00 ff fe 00 3b 43 52 45 41 54 4f 52 3a 20 67 64 2d 6a 70 65 67 20 76 31 2e 30 20 28 75 73 69 ... >,
[0] size: 341398 }
[0] [Object: null prototype] { user: 'Ajanuw' }
獲取文件下載進度
使用send方法發送,可以返回一個監聽流
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Uint8List image;
ImageChunkEvent loadingProgress;
ImageNetworkError error;
var _client = http.Client();
/// request
http.Request get _req {
var req = http.Request(
'get',
Uri.parse(widget.src),
);
if (widget.headers != null) {
for (MapEntry<String, String> m in widget.headers.entries) {
req.headers[m.key] = m.value;
}
}
return req;
}
@override
void initState() {
super.initState();
_init();
}
Future<void> _init() async {
http.StreamedResponse r = await _client.send(_req);
print(r.statusCode);
List<int> ds = [];
r.stream.listen(
(List<int> d) {
ds.addAll(d);
setState(() {
loadingProgress = ImageChunkEvent(
cumulativeBytesLoaded: ds.length, // 當前加載
expectedTotalBytes: r.contentLength, // 總長度
);
});
},
onDone: () {
setState(() {
image = Uint8List.fromList(ds);
loadingProgress = null;
});
_client?.close();
},
);
}
@override
void dispose() {
_client?.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (loadingProgress == null &&
image == null &&
widget.loadingWidget != null) {
return _loadingWidget();
}
if (widget.loadingBuilder != null) {
return _loadingBuilder();
} else {
return Image.memory(image);
}
}
}
創建自己的request
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
final SkyClient skyClient = SkyClient(http.Client());
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('home page'),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.send),
onPressed: () async {
try {
var r = await skyClient.getFirstUser('januwA');
print(r);
} on SocketException catch (e) {
print(e);
}
},
),
);
}
}
class SkyClient extends http.BaseClient {
final http.Client _inner;
SkyClient(this._inner);
@override
Future<http.StreamedResponse> send(http.BaseRequest request) {
return _inner.send(request);
}
@override
Future<http.Response> get(url, {Map<String, String> headers}) {
return _inner.get(url, headers: headers);
}
Future<Map<String, dynamic>> getFirstUser(String name,
{Map<String, String> headers}) async {
var r = await _inner.get("https://api.github.com/search/users?q=$name",
headers: headers);
return jsonDecode(r.body)['items'][0];
}
}
使用攔截器 http_interceptor
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http_interceptor/http_interceptor.dart';
import 'package:path/path.dart' as path;
import 'package:path/path.dart' show Style;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
HttpClientWithInterceptor client = HttpClientWithInterceptor.build(
interceptors: [
BaseUrlInterceptor(),
AuthorizationInterceptor(),
],
);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('home page'),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.send),
onPressed: () async {
try {
final r = await client.get('test');
print(r.body);
} on SocketException catch (e) {
print(e);
}
},
),
);
}
}
class AuthorizationInterceptor implements InterceptorContract {
@override
Future<RequestData> interceptRequest({RequestData data}) async {
try {
data.headers['Authorization'] = "Bearer <TOKEN>";
} catch (e) {
print(e);
}
return data;
}
@override
Future<ResponseData> interceptResponse({ResponseData data}) async {
return data;
}
}
class BaseUrlInterceptor implements InterceptorContract {
final p = path.Context(style: Style.url);
final baseUrl = Uri(
scheme: 'http',
host: '192.168.1.91',
port: 5000,
);
@override
Future<RequestData> interceptRequest({RequestData data}) async {
if (p.isRelative(data.url)) {
data.url = p.normalize(p.join(baseUrl.toString(), data.url));
}
return data;
}
@override
Future<ResponseData> interceptResponse({ResponseData data}) async {
return data;
}
}
下載文件
import 'dart:io';
import 'package:http/http.dart' as http;
main(List<String> args) async {
var r = await http.get("https://i.loli.net/2019/10/01/CVBu2tNMqzOfXHr.png");
print(r.statusCode);
await File('./image.jpg').writeAsBytes(r.bodyBytes);
}
上傳文件獲取上傳進度
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:http/http.dart' as http;
final String __filename = Platform.script.path.replaceFirst('/', '');
final String __dirname = path.dirname(__filename);
final Uri uri = Uri.parse("http://localhost:3000/upload");
final String imgPath = path.join(__dirname, 'test.jpg');
main() async {
final request = await HttpClient().postUrl(uri);
int byteCount = 0;
var requestMultipart = http.MultipartRequest("POST", uri)
..files.addAll([
await http.MultipartFile.fromPath("file", imgPath),
])
..fields.addEntries([
MapEntry("name", "ajanuw"),
]);
request.contentLength = requestMultipart.contentLength;
var msStream = requestMultipart.finalize();
requestMultipart.headers.forEach((k, v) => request.headers.set(k, v));
await request.addStream(msStream.transform(
StreamTransformer.fromHandlers(
handleData: (data, sink) {
sink.add(data);
byteCount += data.length;
print(
"${((byteCount / requestMultipart.contentLength) * 100).toInt()}/${100}");
},
handleError: (error, stack, sink) => print('upload error'),
handleDone: (sink) => sink.close(),
),
));
final httpResponse = await request.close();
print(httpResponse.statusCode);
var contents = StringBuffer();
httpResponse.transform(utf8.decoder).listen(
(String data) => contents.write(data),
onDone: () {
print(contents.toString());
},
);
}
run
> dart .\bin\main.dart
0/100
0/100
80/100
99/100
99/100
100/100
201
upload sucess
serevr
@Post('upload')
@UseInterceptors(FileInterceptor('file'))
UploadedFile(@UploadedFile() file) {
console.log(file);
return "upload sucess";
}
上傳文件獲取上傳進度(2)
import 'dart:async';
import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:http/http.dart' as http;
final String __filename = Platform.script.path.replaceFirst('/', '');
final String __dirname = path.dirname(__filename);
final Uri uri = Uri.parse("http://localhost:3000/upload");
final String imgPath = path.join(__dirname, 'test.jpg');
class MultipartRequest extends http.MultipartRequest {
Function(int bytes, int total) onProgress;
MultipartRequest(String method, Uri url, {this.onProgress})
: super(method, url);
/// 重寫這個方法
@override
http.ByteStream finalize() {
final byteStream = super.finalize();
if (onProgress == null) return byteStream;
final total = this.contentLength;
int bytes = 0;
final t = StreamTransformer.fromHandlers(
handleData: (List<int> data, EventSink<List<int>> sink) {
bytes += data.length;
onProgress(bytes, total);
sink.add(data);
},
);
final stream = byteStream.transform(t);
return http.ByteStream(stream);
}
}
main() async {
var uri = Uri.parse("http://localhost:3000/upload");
http.MultipartRequest request = MultipartRequest(
"POST",
uri,
onProgress: (int bytes, int total) {
print("${((bytes / total) * 100).toInt()}/${100}");
},
);
request.files.add(
await http.MultipartFile.fromPath('file', path.join(__dirname, 'test.jpg')),
);
var r = await request.send();
print(r.statusCode);
print(await r.stream.bytesToString());
}