Unity 下载大文件分步下载,避免Android端内存溢出,出现闪退情况

文件下载器实现

这篇文章将介绍一个简单的文件下载器实现,该实现支持分块下载和显示下载进度。我们将逐步解释代码,并提供必要的注释。

private const int ChunkSize = 10 * 1024 * 1024; // 每个块的大小(1MB)
private long totalSize; // 文件总大小
private long downloadedSize; // 已下载的大小
private FileStream fileStream;

private IEnumerator DownloadCoroutine()
{
    // 发起HTTP请求获取文件大小
    var request = (HttpWebRequest)WebRequest.Create(ConfigMgr.url);//下载地址自己填
    request.Method = "HEAD";
    var response = (HttpWebResponse)request.GetResponse();
    totalSize = response.ContentLength;
    response.Close();
    // 创建文件流   FilePath为保存到的文件流地址说
    fileStream = new FileStream(FilePath, FileMode.Create, FileAccess.ReadWrite);
    // 分块下载
    var chunkIndex = 0;
    while (downloadedSize < totalSize)
    {
        var startRange = downloadedSize;
        var endRange = downloadedSize + ChunkSize - 1;
        if (endRange >= totalSize)
            endRange = totalSize - 1;

        // 发起HTTP请求下载块
        request = (HttpWebRequest)WebRequest.Create(ConfigMgr.url);
        request.AddRange(startRange, endRange);
        response = (HttpWebResponse)request.GetResponse();

        // 读取并写入块数据到文件流
        var buffer = new byte[1024 * 100];
        var bytesRead = response.GetResponseStream().Read(buffer, 0, buffer.Length);
        while (bytesRead > 0)
        {
            fileStream.Write(buffer, 0, bytesRead);
            bytesRead = response.GetResponseStream().Read(buffer, 0, buffer.Length);
        }
        //
        response.Close();
        // 更新已下载的大小
        downloadedSize = endRange + 1;
        // 计算下载进度
        var progress = (float)downloadedSize / totalSize;
        Debug.Log("Download Progress: " + progress.ToString("P"));
        LoadDataPanel.Instance.UpdateSilder(progress, "正在下载资源文件中......" + string.Format("{0:P}", progress));
        yield return null;
        chunkIndex++;
    }

    // 关闭文件流
    fileStream.Close();
    Debug.Log("Download Complete!");
    yield return null;
    StartCoroutine(SaveZip(extractPath));
}

以上是一个用于文件下载的C#代码段。以下是对代码的解释和说明:

  1. 首先,我们通过发起一个HTTP请求来获取要下载的文件的大小。这个请求只使用HTTP头部(HEAD)方法,而不会下载实际的文件内容。获取到的文件大小存储在totalSize变量中。
  2. 接下来,我们创建一个文件流(fileStream)来保存下载的文件内容。文件流的访问模式为读写(FileMode.Create, FileAccess.ReadWrite)。
  3. 通过分块下载的方式来下载文件。每个块的大小为1MB,可以根据需要进行调整。
  4. 在每次循环中,我们计算当前要下载的块的起始范围和结束范围。起始范围为downloadedSize,结束范围为downloadedSize + ChunkSize - 1。如果结束范围超过了文件的总大小(totalSize),则将其设置为总大小减去1。
  5. 使用HTTP请求下载当前块的内容。我们创建一个新的HTTP请求对象,并设置请求范围(request.AddRange(startRange, endRange))来指定要下载的块。然后,我们获取响应对象,并读取响应流中的数据。
  6. 为了逐步将块的数据写入文件流,我们使用一个缓冲区(buffer)来读取响应流中的数据,并使用文件流的Write方法将数据写入文件。
  7. 当块的数据读取和写入完成后,关闭响应对象。
  8. 更新已下载的大小(downloadedSize)为当前块的结束范围加1。计算下载进度,将已下载的大小除以文件总大小得到一个百分比值,并打印下载进度日志。
  9. 在每次循环结束时,更新下载进度的UI显示,然后通过yield return null暂停协程的执行,使得其他操作有机会执行。
  10. 当所有块都下载完成后,关闭文件流并输出下载完成的日志。最后,通过协程调用SaveZip方法来保存和解压缩下载的ZIP文件。

以上是该文件下载器实现的代码解释和说明。这个下载器使用分块下载的方式,可以更有效地下载大型文件,并且可以实时更新下载进度。在使用时,你需要根据实际情况对代码进行适当的调整和扩展。