通过 Dio 我们可以将文件上传到阿里OSS。

    1. import 'dart:convert';
    2. import 'dart:io';
    3. import 'package:crypto/crypto.dart';
    4. import 'package:dio/dio.dart';
    5. import 'package:uuid/uuid.dart';
    6. class HttpUtil {
    7. static HttpUtil instance;
    8. Dio dio;
    9. BaseOptions options;
    10. // oss相关参数
    11. static String ossPath = 'https://xxx.oss-cn-shenzhen.aliyuncs.com';
    12. static String accesskeyId= 'your accesskeyId';
    13. static String accesskeySecret= 'your accesskeySecret';
    14. static String uploadBaseUrl = 'test/flutter';
    15. static String policyText = '{"expiration": "2020-01-01T12:00:00.000Z","conditions": [["content-length-range", 0, '
    16. '1048576000]]}'; // 验证文本域
    17. // 签名相关
    18. static List<int> policyText_utf8 = utf8.encode(policyText); // 进行utf8编码
    19. static String policy_base64 = base64.encode(policyText_utf8); // 进行base64编码
    20. static List<int> policy = utf8.encode(policy_base64); // 再次进行utf8编码
    21. static List<int> key = utf8.encode(accesskeySecret); // 进行utf8 编码
    22. static List<int> signature_pre = new Hmac(sha1, key).convert(policy).bytes; // 通过hmac,使用sha1进行加密
    23. String signature = base64.encode(signature_pre); // 最后一步,将上述所得进行base64 编码
    24. HttpUtil() {
    25. options = BaseOptions(
    26. connectTimeout: 10000,
    27. receiveTimeout: 10000,
    28. headers: {},
    29. );
    30. dio = new Dio(options);
    31. }
    32. oss(File file) async { // 接受一个 File 类型的参数
    33. var ext = file.path.split('.').last; // 获取文件扩展名
    34. var userId = (await Storage.get('userInfo'))['id'].toString();
    35. var now = (new DateTime.now()).toString();
    36. var uuid = new Uuid();
    37. var filename = uuid.v5(Uuid.NAMESPACE_URL, now + userId); // 通过当前时间和userId生成uuid
    38. // 构建 FormData
    39. FormData data = new FormData.from({
    40. 'Filename': '文件名,随意',
    41. 'key' : "$uploadBaseUrl/$filename.$ext",
    42. 'policy': policy_base64,
    43. 'OSSAccessKeyId': accesskeyId,
    44. 'success_action_status' : '200', // 让服务端返回200,不然,默认会返回204
    45. 'signature': signature,
    46. 'file': new UploadFileInfo(file, "imageFileName")
    47. });
    48. try {
    49. Response response = await dio.post(ossPath, data: data);
    50. var uploadPath = "$ossPath/$uploadBaseUrl/$filename.$ext";
    51. print("上传成功: $uploadPath");
    52. return uploadPath; // 返回上传路径
    53. } on DioError catch(e) {
    54. print("上传失败: $e");
    55. }
    56. }
    57. }

    使用的时候:

    1. Future getImage() async {
    2. try {
    3. File image = await ImagePicker.pickImage(source: ImageSource.gallery);
    4. var uploadPath = await HttpUtil().oss(image);
    5. print(uploadPath);
    6. } catch (e) {}
    7. }

    这里, 使用了 ImagePicker 从相册或拍照获取文件, 需要引入包:

    1. import 'package:image_picker/image_picker.dart';

    本文使用到的一些依赖:

    1. dependencies:
    2. dio: ^2.1.0
    3. image_picker: ^0.6.1+4
    4. crypto: ^2.1.3
    5. uuid: ^2.0.1