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