httpWebRequest下载mp4文件
if (nurl.EndsWith("mp4")|| nurl.Contains("mp4"))
{
var savepath = Sharing.StartupPath()+this.getFileName()+".mp4";
var mp4Bytes = HTTP.GetMP4ContentAsync(nurl);
if (mp4Bytes != null && mp4Bytes.Result.Length > 0)
{
try
{
File.WriteAllBytes(savepath, mp4Bytes.Result);
Console.WriteLine("MP4 文件保存成功: " + savepath);
Widget.Ssp.Invoke(Form1.PSetTxt, new object[]
{
1,
"MP4 文件保存成功!"
});
return;
}
catch (Exception ex)
{
Console.WriteLine("保存文件时出错: " + ex.Message);
}
}
else
{
Console.WriteLine("未能获取到有效的 MP4 文件内容。");
}
return;
}
public static async Task<byte[]> GetMP4ContentAsync(string strUrl, string cookie = "", int nTimeOut = 9000)
{
if (string.IsNullOrEmpty(strUrl))
{
return null;
}
HttpWebRequest httpWebRequest = null;
HttpWebResponse httpWebResponse = null;
Util.SetCertificatePolicy();
byte[] contentBytes = null;
try
{
httpWebRequest = (HttpWebRequest)WebRequest.Create(strUrl);
httpWebRequest.Timeout = nTimeOut;
httpWebRequest.ReadWriteTimeout = 60000;
httpWebRequest.AllowAutoRedirect = true;
if (!string.IsNullOrEmpty(cookie))
{
httpWebRequest.Headers.Add("Cookie", cookie);
}
httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (Stream responseStream = httpWebResponse.GetResponseStream())
{
using (MemoryStream memoryStream = new MemoryStream())
{
byte[] buffer = new byte[4096];
int bytesRead;
long totalBytesRead = 0;
long totalBytes = httpWebResponse.ContentLength; // 总字节数
// 读取响应流并写入内存流
while ((bytesRead = await responseStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await memoryStream.WriteAsync(buffer, 0, bytesRead);
// 计算并报告进度
totalBytesRead += bytesRead;
//if (progress != null)
//{
double percentage = (double)totalBytesRead / totalBytes * 100;
//Widget.Ssp.Invoke(Form1.PSetTxt, new object[]
//{
//3,
//Math.Round(percentage, 1).ToString("0.00") + "%"
//});
//Widget.totalProgressBar.Value = (int)percentage;
// progress.Report((int)percentage);
//}
}
contentBytes = memoryStream.ToArray();
}
}
}
catch (Exception ex)
{
HTTP.lastError = ex.Message;
}
finally
{
if (httpWebRequest != null)
{
httpWebRequest.Abort();
}
if (httpWebResponse != null)
{
httpWebResponse.Close();
}
}
return contentBytes;
}
在您提供的代码中,出现 System.OutOfMemoryException 异常的原因是内存不足,即程序尝试分配的内存超过了系统可用的内存限制。
在分析您的代码时,发现以下几个可能导致内存问题的地方:
- 内存流未释放: 使用
MemoryStream类型的memoryStream时,如果在大文件下载过程中未及时释放内存流,会导致内存消耗累积,最终耗尽可用内存。 - 内存流大小限制:使用
MemoryStream类来存储下载的内容。如果下载的文件非常大(例如几个GB),那么尝试将整个文件存储在内存中可能会导致OutOfMemoryException。尤其是在 32 位应用程序中,可用内存受到更严格的限制。 - 大文件处理: 如果下载的文件过大,例如几个 GB 的视频文件,尝试将其整个内容读取到内存中可能会导致
OutOfMemoryException。 - 适当的缓冲区大小:调整读取和写入操作的缓冲区大小,通常可以使用较小的缓冲区(例如 4KB 或 8KB),以减少每次操作时的内存消耗
- 内存泄漏: 如果在循环中处理内存流时出现异常或处理不当,可能会导致内存泄漏,进而导致内存消耗过多。
为了解决这个问题,建议您进行以下调整和改进:
- 分块处理: 不要一次性将整个文件内容读取到内存中,而是使用适当大小的缓冲区(比如您代码中的 4096 字节的
buffer),分块读取文件内容,然后立即写入目标文件或处理。 - 释放资源: 确保使用
using语句或显式地调用Dispose方法来释放MemoryStream和其他使用资源的对象。 - 内存监控: 在循环处理过程中,监控内存使用情况,可以通过.NET性能分析工具或操作系统自带的性能监控工具来查看程序的内存消耗情况,及时发现问题。
下面是一种改进的示例,仅供参考,具体根据您的应用场景和需求进行调整:
改为边下载边存储文件:使用流式处理:不要尝试一次性将整个文件加载到内存中。而是在读取响应流时,直接将数据写入目标文件(或者处理数据的其他方式),这样可以避免大内存占用。
改进说明:
- 异步处理:使用
HTTP.GetMP4ContentAsync(nurl)异步获取 MP4 文件内容。在这里,通过Task.Result等待异步操作完成。 - 流式写入:使用
FileStream将文件内容逐步写入到指定路径的文件中,避免一次性将大文件内容存储在内存中。
httpWebRequest流式写入下载mp4文件
var result= await HTTP.GetMP4ContentAsync(nurl,savepath);
if (result)
{
OndwonCompleted(EventArgs.Empty);
}
else
{
Widget.Ssp.Invoke(Form1.PSetTxt, new object[]
{
1,
"MP4 文件下载失败,请重试!"
});
}
public static async Task<bool> GetMP4ContentAsync(string strUrl, string savePath, string cookie = "", int nTimeOut = 90000)
{
if (string.IsNullOrEmpty(strUrl))
{
return false;
}
HttpWebRequest httpWebRequest = null;
HttpWebResponse httpWebResponse = null;
Util.SetCertificatePolicy();
//byte[] contentBytes = null;
try
{
httpWebRequest = (HttpWebRequest)WebRequest.Create(strUrl);
httpWebRequest.Timeout = nTimeOut;
httpWebRequest.ReadWriteTimeout = 60000;
httpWebRequest.AllowAutoRedirect = true;
if (!string.IsNullOrEmpty(cookie))
{
httpWebRequest.Headers.Add("Cookie", cookie);
}
httpWebResponse = (HttpWebResponse)await httpWebRequest.GetResponseAsync();
using (Stream responseStream = httpWebResponse.GetResponseStream())
{
using (FileStream fileStream = new FileStream(savePath, FileMode.Create, FileAccess.Write))
{
try
{
byte[] buffer = new byte[4096];
int bytesRead;
long totalBytesRead = 0;
long totalBytes = httpWebResponse.ContentLength; // 总字节数
// 读取响应流并写入内存流
while ((bytesRead = await responseStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await fileStream.WriteAsync(buffer, 0, bytesRead);
// 计算并报告进度
totalBytesRead += bytesRead;
//if (progress != null)
//{
double percentage = (double)totalBytesRead / totalBytes * 100;
if (percentage > 68)
{
Console.WriteLine(percentage);
}
Sharing.setlinks(Math.Round((percentage),1).ToString()+"%");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Widget.Ssp.Invoke(Form1.PSetTxt, new object[]
{
1,
"MP4 文件保存成功!"
});
return true;
}
}
catch (Exception ex)
{
HTTP.lastError = ex.Message;
}
finally
{
if (httpWebRequest != null)
{
httpWebRequest.Abort();
}
if (httpWebResponse != null)
{
httpWebResponse.Close();
}
}
return false;
}