1. 程式人生 > >Flutter使用騰訊雲COS物件服務

Flutter使用騰訊雲COS物件服務

官方文件:請求籤名, Get Object

轉載請註明出處: https://www.jianshu.com/p/49fe86909d18

Overview

本文使用dart按照騰訊COS文件生成簽名,並使用簽名下載COS檔案物件到本地(使用flutter_download包)

載入crypto以及flutter_downloader包

pubspec.yaml檔案中加入依賴(flutter_downloader文件,crypto文件

Android: flutter_downloader 需要配置許可權,請參考其文件。

dependencies:
  flutter:
    sdk: flutter
    ........
  crypto: ^2.0.6
  flutter_downloader: ^1.1.3

實現cos簽名以及下載檔案

import 'dart:convert';

import 'package:crypto/crypto.dart';
import 'package:flutter_downloader/flutter_downloader.dart';

class TencentCos {
  static bool debug = true;
  /// auth signature expired time in seconds
  static final int signExpireTimeInSeconds = '10';

  static final String secretId = 'tencentSerertId';
  static final String secretKey = 'tencentSecretKey';
  static final String bucketHost = 'yourBucketHost'; // xxx-xxxxxx.cos.ap-chengdu.myqcloud.com

  static TencentCos _cos;

  TencentCos._();

  static TencentCos get() {
    if (_cos == null) {
      _cos = TencentCos._();
    }

    return _cos;
  }

 /// download $fileName and save to $saveDir(absolute path)
  Future<String> downloadFile(String fileName, String saveDir) async {
    var url = '/$fileName';
    final taskId = await FlutterDownloader.enqueue(
      headers: buildHeaders(url),
      url: 'https://$bucketHost$url',
      savedDir: saveDir,
      fileName: fileName,
      showNotification: false,
      // show download progress in status bar (for Android)
      openFileFromNotification: false,
      // click on notification to open downloaded file (for Android)
    );
    return taskId;
  }

  Map<String, String> buildHeaders(String url) {
    Map<String, String> headers = Map();
    headers['HOST'] = bucketHost;
    headers['Authorization'] = _auth('get', url, headers: headers);
    if(debug) {
      print(headers);
    }
    return headers;
  }

  String _auth(String httpMethod, String httpUrl,
  {Map<String, String> headers, Map<String, String> params}) {
    headers = headers ?? Map();
    params = params ?? Map();

    int currentTimestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000;
    var keyTime =
        '$currentTimestamp;${currentTimestamp + signExpireTimeInSeconds}';
    headers = headers.map((key, value) => MapEntry(key.toLowerCase(), value));
    params = params.map((key, value) => MapEntry(key.toLowerCase(), value));
    List<String> headerKeys = headers.keys.toList();
    headerKeys.sort();
    var headerList = headerKeys.join(';');
    var httpHeaders = headerKeys
        .map((item) => '$item=${Uri.encodeFull(headers[item])}')
        .join('&');

    List<String> paramKeys = params.keys.toList();
    paramKeys.sort();
    var urlParamList = paramKeys.join(';');
    var httpParameters = paramKeys
        .map((item) => '$item=${Uri.encodeFull(params[item])}')
        .join('&');

    var signKey = new Hmac(sha1, utf8.encode(secretKey))
        .convert(utf8.encode(keyTime));
    String httpString =
        '${httpMethod.toLowerCase()}\n$httpUrl\n$httpParameters\n$httpHeaders\n';
    var httpStringData = sha1.convert(utf8.encode(httpString));
    String stringToSign = 'sha1\n$keyTime\n$httpStringData\n';
    var signature =
        new Hmac(sha1, utf8.encode(signKey.toString())).convert(utf8.encode(stringToSign));

    String auth =
        'q-sign-algorithm=sha1&q-ak=$secretId&q-sign-time=$keyTime&q-key-time=$keyTime&q-header-list=$headerList&q-url-param-list=$urlParamList&q-signature=$signature';
    return auth;
  }
}

使用示例

static final TencentCos _cos = TencentCos.get();

 Future<String> _findLocalPath() async {
    final directory = widget.platform == TargetPlatform.android
        ? await getExternalStorageDirectory()
        : await getApplicationDocumentsDirectory();
    return directory.path;
  }

Future _requestDownload() async {
    ///  $yourLocalSaveDir is relative path
     var _localPath = (await _findLocalPath()) + '$yourLocalSaveDir';  
     var taskId = await _cos.downloadFile('$yourFileNameInCos', _localPath);
  }

更多

可根據自己需求,使用buildHeaders生成帶簽名的請求頭,進行https請求。