首页 > 其他分享 >Flutter获取大文件MD5值的方法以及大文件实现分块上传和断点续传

Flutter获取大文件MD5值的方法以及大文件实现分块上传和断点续传

时间:2023-12-26 22:00:32浏览次数:33  
标签:raf 文件 currentPart int start 断点续传 partSize Flutter fileSize

Flutter获取大文件MD5值的方法

最近一直在搞flutter,有一个需求是将一个不到1G的大文件从App端上传到服务器,为了做文件校验所以要获取到文件的MD5。 1.第一步首先获取到文件,并计算出文件大小和分快的数目

File file = File(path);
int fileSize = file.lengthSync();
int totalPart = (fileSize * 1.0 / partSize).ceil();
static const int partSize = 1024 * 1024 * 3; //默认3m每块

2.第二步导入flutter 官方的convert库

import 'package:convert/convert.dart' as convert;/起一个别名
int start; //开始读文件的位置
int length; //读取文件的长度
var output = convert1.AccumulatorSink<Digest>();
var input = md5.startChunkedConversion(output);//这是一个sink 会把所有块的md5拼接到一起

3.第三部循环所有分快

int currentPart = 0;
while (currentPart < totalPart) {
      //文件开始读取的位置
      start = currentPart * partSize;
      //读取的长度 最后一块直接到文件长度
      length = (start + partSize > fileSize) ? (fileSize - start ) : partSize;
      //每块读取的位置
      RandomAccessFile raf = file.openSync(mode: FileMode.read);
      raf.setPositionSync(start);
      Uint8List data = raf.readSync(length);
    
      input.add(data);
      currentPart++;
}

4.获取最终md5,关闭sink

input.close();
    var digest = output.events.single.toString();
    return digest;

5.完整方法调用

String _getMd5(String path) {
    File file = File(path);

    int fileSize = file.lengthSync();
    int totalPart = (fileSize * 1.0 / partSize).ceil();

    int start; //开始读文件的位置
    int length; //读取文件的长度
    var output = convert.AccumulatorSink<Digest>();
    var input = md5.startChunkedConversion(output);

    int currentPart = 0;
    while (currentPart < totalPart) {
      start = currentPart * partSize;
      length = (start + partSize > fileSize) ? (fileSize - start ) : partSize;

      RandomAccessFile raf = file.openSync(mode: FileMode.read);
      raf.setPositionSync(start);
      Uint8List data = raf.readSync(length);
      input.add(data);
      currentPart++;
    }

    input.close();
    var digest = output.events.single.toString();
    return digest;
  }

大文件实现分块上传和断点续传

1.将文件进行分块,我们和后台约定的是3M每块

static const int partSize = 1024 * 1024 * 3; //3m每块
///上传文件 后台要记录从第几块开始传,也就是currentPart
Future<bool> _uploadZip(String path) async {
    File file = File(path);
    String fileName = FileUtil.getBaseName(file.path);
    int fileSize = file.lengthSync(); //文件总大小
    int totalPart = (fileSize * 1.0 / partSize).ceil(); //分块总数 向上取整
    int currentPart = currentPart; //当前要传第几块 由后台记录返回的
   RandomAccessFile raf = file.openSync(mode: FileMode.read);
   //开启循环上传每一块
    while (currentPart < totalPart) {
      bool isOK = await _uploadPart(file, currentPart, totalPart, fileSize, fileName,raf);
      if (!isOK) {
        invokeStateListener(ProgressState.error, null);
        raf.closeSync();
        return false;
      }
      //更新进度
      invokeProgressListeners((currentPart + 1) * 1.0 / totalPart);
      currentPart++;
    }
     raf.closeSync();
    //所有分快上传成功
    invokeStateListener(ProgressState.complete, null);
    return true;
  }

2.将每一个分块上传到后台,并记录上传是否成功

Future<bool> _uploadPart(File file, int currentPart, int totalPart, int fileSize, String fileName,RandomAccessFile raf) async {
    //开始读文件的位置     
    int start = currentPart * partSize; 
    //读取文件的长度 注意不要让长度超过总长度
    var length = (start + partSize > fileSize) ? (fileSize - start) : partSize; 
    raf.setPositionSync(start);
    Uint8List data = raf.readSync(length);//从文件总长度中截取出要上传的长度

    Map<String, dynamic> map = {};
    map['total'] = totalPart; //总块数
    map['currentPart'] = currentPart; //当前上传到第几块
    map['part'] = MultipartFile.fromBytes(data, filename:'随便设置文件名');//当前快的数据 

    Map<String, dynamic>? response = await 真正的上传函数
    //自定义逻辑 失败的话返回false
 
    return true;
  }

标签:raf,文件,currentPart,int,start,断点续传,partSize,Flutter,fileSize
From: https://blog.51cto.com/u_16175630/8988145

相关文章

  • pycharm文件中配置.gitignore后没有起作用,未生效
    原因:这是因为pycharm会自动运行gitadd.的功能,所以.gitignore修改后,需要手动清空cached的内容,然后再add一次,这时gitignore会起作用。解决办法:在pycharm命令里输入:gitrm-r--cached.#也可以指定文件清理缓存gitadd.慎用(以下可以不用操作):gitcommit-m"更新过滤规......
  • 前端上传文件或者上传文件夹
    文档https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input上传文件夹,主要的参数webkitdirectory浏览器上传文件夹,浏览器会弹出询问窗口 兼容性https://caniuse.com/?search=webkitdirectory 代码如下<!--选择文件--><div><labelfor="upload-file">点......
  • 软件测试/测试开发|Ubuntu系统常用文件管理命令详解
    前言Ubuntu是一种广泛使用的Linux操作系统,提供了丰富而强大的文件管理命令,使用户能够通过命令行轻松管理文件和目录。本文将介绍一些常用的Ubuntu文件管理命令,帮助用户更好地理解和利用系统资源。ls-列出目录内容ls[选项][目录]ls命令用于列出目录中的文件和子目录。......
  • iTunes备份文件转换----iTunesBackupTransfer
    iTunesBackupTransfer我的github被标记了,还在和客服对线,现在是访问不了的,包括之前的面板一把梭。目前还不支持加密备份转换,手头没有素材,后面再说吧。。。找软件是一个麻烦事,一搜大把的都是商业软件,要么就去找破解版,要么就硬搞试用,还是写一个吧。着急想用的可以直接找我要,不着......
  • 前端实现文件上传(点击+拖拽)
    一、简介之前在Vue项目中使用过element的上传组件,实现了点击上传+拖拽上传的两种上传功能。然后我就在想是否可以通过原生的html+js来实现文件的点击上传和拖拽上传,说干就干。首先是点击获取上传文件自然没的说,只需要借助input标签即可,但原生的点击上传按钮,实在是过于简陋,所以我的......
  • 如何获取文件缩略图
    在C++中,可以有以下两种办法使用COM接口IThumbnailCache文档链接:https://learn.microsoft.com/en-us/windows/win32/api/thumbcache/nn-thumbcache-ithumbnailcache示例代码如下:1VOIDGetFileThumbnail(PCWSTRpath)2{3HRESULThr=CoInitialize(nullptr);4......
  • 弹性布局 flex 的公共的css文件
    /*弹性布局*/.flex{display:flex;}.flex1{flex:1;}.flex-column{flex-direction:column;}.justify-start{justify-content:flex-start;}.justify-end{justify-content:flex-end;}.justify-center{justify-content:center;}.justify-betw......
  • Voc2Json--挑选voc中的类别生成json文件
      importargparseimportjson,shutilimportos,sysimportxml.etree.ElementTreeasETparent=os.path.dirname(os.path.realpath(__file__))gadent=os.path.dirname(parent)sys.path.insert(0,gadent)sys.path.append(gadent)fromutils.toolimportlis......
  • python .gitignore 文件模板 & 相关注意事项
    参考:https://blog.csdn.net/qq_38122800/article/details/132663030https://blog.csdn.net/weixin_42289273/article/details/122912938https://zhuanlan.zhihu.com/p/22494724在使用git进行代码版本管理时,对于不想提交的部分内容,可以通过.gitignore文件来配置提交时......
  • 文件概述补充
    ......