详情页标题前

腾讯云对象存储Flutter 直传实践

详情页1

简介

文档介绍如何不依赖 SDK,用简单的代码,在 Flutter 端直传文件到对象存储(Cloud Object Storage,COS)的存储桶。注意:本文档内容基于 XML 版本的 API

前提条件

1. 登录 COS 控制台 并创建存储桶,得到 Bucket(存储桶名称) 和 Region(地域名称),详情请参见 创建存储桶 文档。2. 登录 访问管理控制台, 获取您的项目 SecretId 和 SecretKey。

实践步骤

整体步骤逻辑为:1. 客户端调用服务端接口传入文件后缀,服务端根据后缀和时间戳等生成 cos key 以及直传的 url。2. 服务端通过 sts sdk 获取临时密钥。3. 服务端用获取到的临时密钥对直传 url 进行签名并返回 url、签名、token 等信息。4. 客户端获取到步骤 3 中的信息后,直接发起 put 请求并携带签名、token 等 header 进行上传。具体代码可参考:Flutter 示例

服务端

注意:正式部署时服务端请加一层您的网站本身的权限检验。出于安全考虑,后端获取临时密钥后生成直传 url 并直接对其进行签名,可参考 Server 示例
具体步骤为:
1. 通过sts sdk获取临时密钥。2. 根据后缀名生成 cos key 以及直传 url相关。3. 使用临时密钥对直传 url 进行签名并返回直传 url、签名、token 等信息服务端配置步骤:1. 配置好密钥、bucket以及region。

var config = {  // 获取腾讯云密钥,建议使用限定权限的子用户的密钥 https://console.cloud.tencent.com/cam/capi  secretId: process.env.COS_SECRET_ID,  secretKey: process.env.COS_SECRET_KEY,  // 密钥有效期  durationSeconds: 1800,  // 这里填写存储桶、地域,例如:test-1250000000、ap-guangzhou  bucket: process.env.PERSIST_BUCKET,  region: process.env.PERSIST_BUCKET_REGION,  // 限制的上传后缀  extWhiteList: ['jpg', 'jpeg', 'png', 'gif', 'bmp'],};

2. 终端执行

npm install

3. 启动服务

node app.js

到这里服务端就启动成功了,可以开始客户端的流程。如有其他语言或自行实现可以参考以下流程:1. 向服务端获取临时密钥,服务端首先使用固定密钥 SecretId、SecretKey 向 STS 服务获取临时密钥,得到临时密钥 tmpSecretId、tmpSecretKey、sessionToken,详情请参考 临时密钥生成及使用指引cos-sts-sdk 文档。2. 对直传 url 进行签名,生成 authorization。3. 返回直传 url、authorization、sessionToken等信息,客户端上传文件时将得到的签名和 sessionToken,分别放到发请求时 header 的 authorization 和 x-cos-security-token 字段里。

客户端(Flutter)

具体代码可参考:Flutter 示例

使用 dio 网络库

1. 从服务端请求直传和签名信息。

/// 获取直传的url和签名等/// @param ext 文件后缀 直传后端会根据后缀生成cos key/// @return 直传url和签名等static Future<Map> getStsDirectSign(String ext) async {  Dio dio = Dio();  //直传签名业务服务端url(正式环境 请替换成正式的直传签名业务url)  //直传签名业务服务端代码示例可以参考:https://github.com/tencentyun/cos-demo/blob/main/server/direct-sign/nodejs/app.js  //10.91.22.16为直传签名业务服务器的地址 例如上述node服务,总之就是访问到直传签名业务服务器的url  Response response = await dio.get('http://10.91.22.16:3000/sts-direct-sign',      queryParameters: {'ext': ext});  if (response.statusCode == 200) {    if (kDebugMode) {      print(response.data);    }    if (response.data['code'] == 0) {      return response.data['data'];    } else {      throw Exception(          'getStsDirectSign error code: ${response.data['code']}, error message: ${response.data['message']}');    }  } else {    throw Exception(        'getStsDirectSign HTTP error code: ${response.statusCode}');  }}

2. 使用获取到的直传和签名信息开始上传文件

/// 上传文件/// @param filePath 文件路径/// @param progressCallback 进度回调static Future upload(String filePath, ProgressCallback progressCallback) async {  String ext = path.extension(filePath).substring(1);  Map directTransferData;  try {    directTransferData = await getStsDirectSign(ext);  } catch (err) {    if (kDebugMode) {      print(err);    }    throw Exception("getStsDirectSign fail");  }  String cosHost = directTransferData['cosHost'];  String cosKey = directTransferData['cosKey'];  String authorization = directTransferData['authorization'];  String securityToken = directTransferData['securityToken'];  String url = 'https://$cosHost/$cosKey';  File file = File(filePath);  Options options = Options(    method: 'PUT',    headers: {      'Content-Length': await file.length(),      'Content-Type': 'application/octet-stream',      'Authorization': authorization,      'x-cos-security-token': securityToken,      'Host': cosHost,    },  );  try {    Dio dio = Dio();    Response response = await dio.put(url,        data: file.openRead(),        options: options, onSendProgress: (int sent, int total) {          double progress = sent / total;          if (kDebugMode) {            print('Progress: ${progress.toStringAsFixed(2)}');          }          progressCallback(sent, total);        });    if (response.statusCode == 200) {      if (kDebugMode) {        print('上传成功');      }    } else {      throw Exception("上传失败 ${response.statusMessage}");    }  } catch (error) {    if (kDebugMode) {      print('Error: $error');    }    throw Exception("上传失败 ${error.toString()}");  }}

使用原生 Http Client 网络库

1. 从服务端请求直传和签名信息。

/// 获取直传的url和签名等/// @param ext 文件后缀 直传后端会根据后缀生成cos key/// @return 直传url和签名等static Future<Map> _getStsDirectSign(String ext) async {  HttpClient httpClient = HttpClient();  //直传签名业务服务端url(正式环境 请替换成正式的直传签名业务url)  //直传签名业务服务端代码示例可以参考:https://github.com/tencentyun/cos-demo/blob/main/server/direct-sign/nodejs/app.js  //10.91.22.16为直传签名业务服务器的地址 例如上述node服务,总之就是访问到直传签名业务服务器的url  HttpClientRequest request = await httpClient      .getUrl(Uri.parse("http://10.91.22.16:3000/sts-direct-sign?ext=$ext"));  HttpClientResponse response = await request.close();  String responseBody = await response.transform(utf8.decoder).join();  if (response.statusCode == 200) {    Map json = jsonDecode(responseBody);    if (kDebugMode) {      print(json);    }    httpClient.close();    if (json['code'] == 0) {      return json['data'];    } else {      throw Exception(          'getStsDirectSign error code: ${json['code']}, error message: ${json['message']}');    }  } else {    httpClient.close();    throw Exception(        'getStsDirectSign HTTP error code: ${response.statusCode}');  }}

2. 使用获取到的直传和签名信息开始上传文件

/// 上传文件/// @param filePath 文件路径/// @param progressCallback 进度回调static Future upload(String filePath, ProgressCallback progressCallback) async {  // 获取直传签名等信息  String ext = path.extension(filePath).substring(1);  Map directTransferData;  try {    directTransferData = await _getStsDirectSign(ext);  } catch (err) {    if (kDebugMode) {      print(err);    }    throw Exception("getStsDirectSign fail");  }
String cosHost = directTransferData['cosHost']; String cosKey = directTransferData['cosKey']; String authorization = directTransferData['authorization']; String securityToken = directTransferData['securityToken']; String url = 'https://$cosHost/$cosKey';
File file = File(filePath); int fileSize = await file.length(); HttpClient httpClient = HttpClient(); HttpClientRequest request = await httpClient.putUrl(Uri.parse(url)); request.headers.set('Content-Type', 'application/octet-stream'); request.headers.set('Content-Length', fileSize.toString()); request.headers.set('Authorization', authorization); request.headers.set('x-cos-security-token', securityToken); request.headers.set('Host', cosHost); request.contentLength = fileSize; Stream<List> stream = file.openRead(); int bytesSent = 0; stream.listen( (List chunk) { bytesSent += chunk.length; double progress = bytesSent / fileSize; if (kDebugMode) { print('Progress: ${progress.toStringAsFixed(2)}'); } progressCallback(bytesSent, fileSize); request.add(chunk); }, onDone: () async { HttpClientResponse response = await request.close(); if (response.statusCode == 200) { if (kDebugMode) { print('上传成功'); } } else { throw Exception("上传失败 $response"); } }, onError: (error) { if (kDebugMode) { print('Error: $error'); } throw Exception("上传失败 ${error.toString()}"); }, cancelOnError: true, );}

相关文档

若您有更丰富的接口调用需求,请参考 Flutter SDK
对象存储官网1折活动,限时活动,即将结束,速速收藏
同尘科技腾讯云授权服务中心。
购买腾讯云产品享受折上折,更有现金返利。同意关联立享优惠

转转请注明出处:https://www.yunxiaoer.com/144494.html

(0)
上一篇 2023年12月9日
下一篇 2023年12月9日
详情页2

相关推荐

  • 腾讯云轻量应用服务器新手指引云小二

    1. 熟悉轻量应用服务器基础知识 什么是轻量应用服务器 TencentCloud Lighthouse?轻量应用服务器与云服务器 CVM 的区别是什么?为什么选择轻量应用服务器?轻量应用服务器应用场景介绍使用轻量应用服务器有哪些限制? 2. 轻量应用服务器的计费模式 腾讯云轻量应用服务器计费分为基础套餐、套餐外超额流量、自定义镜像 及云硬盘四部分。其中,基础…

    2023年12月9日
  • 腾讯云裸金属云服务器退回和销毁及退费

    您可以在控制台自助退回或者销毁不再使用的黑石物理服务器,退回或者销毁后数据将被清除,请注意保存数据。 关于清除数据的说明 计费模式为【预付费 – 包年包月】或者【后付费 – 月结】的物理服务器退回后将立即隔离并移入回收站,此时服务器将不能访问。并在回收站保留数据7天,7天后不再恢复的将清除数据并回收服务器。计费模式为【后付费 &#82…

    2023年12月9日
  • 腾讯云容器服务使用 CLB 实现简单的蓝绿发布和灰度发布同尘科技

    操作场景 腾讯云 Kubernetes 集群实现蓝绿发布或灰度发布通常需向集群额外部署其他开源工具,例如 Nginx Ingress、Traefik 或将业务部署至服务网格 Service Mesh,利用服务网格的能力实现。这些方案均具有一定难度,若您的蓝绿发布或灰度需求不复杂,且不期望集群引入过多的组件或复杂的用法,则可参考本文利用 Kubernetes …

    2023年12月9日
  • 信息流广告,信息流部分建议宽度830px,只针对默认列表样式,顺序随机
  • 阿里云负载均衡管理闲置实例-云淘科技

    闲置实例向您展示超过7天未投入使用的后付费实例,关注闲置实例有助于您更好的管理成本。 背景信息 超过7天未使用,且满足以下任一条件的后付费CLB实例为闲置实例: 实例处于已停止状态 实例没有配置监听 实例的监听已全部停止 实例没有添加后端服务器 实例所有的后端服务器的权重为0 重要 闲置实例仍会计费,CLB实例只有释放后才会停止计费。更多信息,请参见CLB实…

    2023年12月10日
  • 腾讯云云点播客户端上传加速

    客户端上传加速可为客户提供更高质量的上传服务。该功能基于腾讯云全球部署的加速网络,根据用户的请求,智能地选择最佳接入点和最优链路,提高上传的速度和成功率。同时支持使用 QUIC 协议进行数据传输,改善数据传输的效率和在弱网环境中的稳定性。 影响上传质量的主要因素 长距离传输 腾讯云在全球很多地区部署了存储中心,客户可以选择性地启用这些存储中心,并且在上传时就…

    2023年12月9日

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
本站为广大会员提供阿里云、腾讯云、华为云、百度云等一线大厂的购买,续费优惠,保证底价,买贵退差。