文件校验&断点续传

热更方案下从服务器下载资源以及必备的文件校验和断点续传功能

一、文件校验

  1. 思路

文件校验是为了防止下载的资源不完整导致运行出错,一般思路是对比服务器端文件和下载到本地的文件的MD5值,检测文件是否下载完整,如果MD5不一致则重新下载。

HTTP协议新增了 Content-MD5 HTTP头,所以可以在请求头中拿到服务器文件的MD5值,但目前我这边使用Nginx服务器代理,并不支持添加该字段(官方说以后也不会有,毕竟每次都要读取整个文件来获取MD5值,拖慢响应速度),所以如果用了Nginx,需要额外安装 File-MD5 模块,然后添加到响应头中。

  1. MD5

简单介绍一下MD5算法,它是一种消息摘要算法,输入不定长信息,输出一个128位(16BYTES)的散列值,用于确保信息传输完整一致。但目前已被证实存在弱点,可以被加以破解,所以如果是需要高度安全性的内容,慎用

  1. C#提供了计算MD5的工具
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public byte[] GetFileMD5(string path)
    {
    using(FileStream fileStream = File.OpenRead(path))
    {
    using(var crypto = MD5.Create())
    {
    var md5 = crypto.ComputeHash(fileStream);
    Debug.Log(md5);
    return md5;
    }
    }
    }

二、断点续传

  1. 思路
  • 发送一个请求获取响应头
  • 获取文件大小和文件MD5值
  • 计算本地已下载文件的大小
  • 在请求头中通过Range请求资源未下载的部分
  • 循环直到下载完成
  • 文件校验 释放资源
  1. 代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    IEnumerator DownloadAssetBundles(string url, string path)
    {
    // 发一个请求获取响应头
    UnityWebRequest headRequest = UnityWebRequest.Head(url);
    yield return headRequest.SendWebRequest();
    if(!string.IsNullOrEmpty(headRequest.error))
    {
    Debug.Log(headRequest.error);
    yield break;
    }
    // 响应头中获取文件大小
    ulong totalLength = ulong.Parse(headRequest.GetResponseHeader("Content-Length"));
    Debug.Log(headRequest.GetResponseHeader("Content-MD5"));
    headRequest.Dispose();

    webRequest = UnityWebRequest.Get(url);
    // append属性设置为true,文件写入方式为接续写入
    webRequest.downloadHandler = new DownloadHandlerFile(path, true);
    // 获取本地已下载文件的大小
    FileInfo fileInfo = new FileInfo(path);
    ulong fileLength = (ulong)fileInfo.Length;
    // 请求头 Range 请求资源未下载的部分内容
    webRequest.SetRequestHeader("Range", "bytes=" + fileLength + "-");
    if(fileLength < totalLength)
    {
    webRequest.SendWebRequest();
    while(!webRequest.isDone)
    {
    double progress = (webRequest.downloadedBytes + fileLength) / (double)totalLength;
    Debug.Log("当前进度:" + progress);
    yield return null;
    }
    }

    // 判断是否下载完成 释放资源
    if(string.IsNullOrEmpty(webRequest.error))
    {
    Debug.Log("下载成功");
    }
    else
    {
    Debug.Log(webRequest.error);
    }
    webRequest.Dispose();
    }

文件校验&断点续传
https://baifabaiquan.cn/2023/03/16/文件校验&断点续传/
作者
白发败犬
发布于
2023年3月16日
许可协议