Dart 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);
    });
  }

打印結果git

$ dart ./bin/main.dart
請求開始
關閉這個請求
Connection closed before full header was received

發送文件到服務器

客服端:github

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());
}

服務器端代碼片斷:json

@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';
  }

執行客服端代碼:api

λ 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方法發送,能夠返回一個監聽流app

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;
  }
}
相關文章
相關標籤/搜索