此文记录的是下载网络文件的操作类。
/***
网络文件下载器
Austin Liu 刘恒辉
Project Manager and Software Designer
E-Mail: lzhdim@163.com
Blog: http://lzhdim.cnblogs.com
Date: 2024-01-15 15:18:00
使用方法:
DownloadWebFileUtil.DownloadFile("https://lzhdim.cnblogs.com/default.html","d:\default.html"):
***/
namespace Lzhdim.LPF.Utility
{
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
/// <summary>
/// 下载网页操作类
/// </summary>
public static class DownloadWebFileUtil
{
/// <summary>
/// 同步下载方法,支持断点续传,计算下载速度,下载进度
/// </summary>
/// <param name="url">下载链接</param>
/// <param name="savePath">文件保存路径,C://xxx.zip</param>
/// <param name="progressCallBack">进度回调</param>
/// <param name="downloadMsgCallBack">速度回调</param>
/// <returns>true:下载成功,false:下载失败</returns>
public static bool DownloadFile(string url, string savePath, Action<double> progressCallBack = null, Action<string> downloadMsgCallBack = null)
{
ServicePointManager.DefaultConnectionLimit = 50;
string responseContent = "";
HttpWebRequest httpWebRequest = null;
try
{
if (string.IsNullOrEmpty(savePath))
return false;
long rangeBegin = 0;//记录已经下载了多少
if (File.Exists(savePath))
rangeBegin = new FileInfo(savePath).Length;
if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
{
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
httpWebRequest = WebRequest.Create(url) as HttpWebRequest;
}
else
httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
//httpWebRequest.Timeout = 300000;
//httpWebRequest.ReadWriteTimeout = 60 * 1000;
httpWebRequest.Method = "GET";
httpWebRequest.KeepAlive = false;
httpWebRequest.ServicePoint.Expect100Continue = false;
httpWebRequest.Proxy = null;
if (rangeBegin > 0)
httpWebRequest.AddRange(rangeBegin);
using (HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse())
{
using (Stream responseStream = httpWebResponse.GetResponseStream())
{
if (responseStream == null)
return false;
long totalLength = httpWebResponse.ContentLength;
if (totalLength == rangeBegin)
{
progressCallBack?.Invoke(100);
return true;
}
if (totalLength == 0 || rangeBegin > totalLength)
{
progressCallBack?.Invoke(0);
return false;
}
long offset = rangeBegin;
long oneSecondDonwload = 0;
var beginSecond = DateTime.Now.Second;
//savePath = Path.Combine(savePath,
httpWebResponse.ResponseUri.LocalPath.Substring(
httpWebResponse.ResponseUri.LocalPath.LastIndexOf('/') + 1)); //自动获取文件名
using (Stream stream = new FileStream(savePath, FileMode.Append, FileAccess.Write))
{
byte[] bArr = new byte[1024 * 8 * 1024];
int size = 0;
while ((size = responseStream.Read(bArr, 0, (int)bArr.Length)) > 0)
{
try
{
stream.Write(bArr, 0, size);
oneSecondDonwload += size;
offset = offset + size;
var endSencond = DateTime.Now.Second;
if (beginSecond != endSencond)
{
string outSize = GetFileSizeTypeBySize(oneSecondDonwload / (endSencond - beginSecond));
downloadMsgCallBack?.Invoke($"{outSize}/S");
beginSecond = DateTime.Now.Second;
oneSecondDonwload = 0;
}
progressCallBack?.Invoke(Math.Round((offset / (totalLength * 1.0)) * 100, 2));
}
catch
{
return false;
}
}
responseContent = savePath;
}
}
httpWebResponse?.Close();
}
}
catch
{
responseContent = "";
return false;
}
finally
{
httpWebRequest?.Abort();
}
return true;
}
/// <summary>
/// 根据URL获取XML文档文本内容
/// </summary>
/// <param name="URL">XML文件网址</param>
/// <returns>XML文本内容</returns>
internal static string GetWebXMLFile(string URL)
{
try
{
start:
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(URL);
req.Method = "GET";
req.Timeout = 60000;
req.KeepAlive = true;
req.AllowAutoRedirect = true;
HttpWebResponse rps = (HttpWebResponse)req.GetResponse();
if (rps.StatusCode != HttpStatusCode.OK)
{
goto start;
}
Stream respStream = rps.GetResponseStream();
using (StreamReader reader = new StreamReader(respStream, Encoding.GetEncoding("utf-8")))
{
//ReadToEnd方法不好使,有时候抛异常:无法从传输连接中读取数据: 远程主机强迫关闭了一个现有的连接
//string text = reader.ReadToEnd();
string text = string.Empty;
string line = string.Empty;
while ((line = reader.ReadLine()) != null)
{
text += line;
}
reader.Close();
return text;
}
}
catch
{
return string.Empty;
}
}
#region 私有函数
/// <summary>
/// 临时返回函数
/// </summary>
/// <param name="sender"></param>
/// <param name="certificate"></param>
/// <param name="chain"></param>
/// <param name="sslPolicyErrors"></param>
/// <returns></returns>
private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}
/// <summary>
/// 获取文件大小
/// </summary>
/// <param name="fileSize">文件大小</param>
/// <returns>格式化后的文本</returns>
private static string GetFileSizeTypeBySize(long fileSize)
{
if (fileSize < 1024)
return $"{fileSize}B";
if (fileSize / 1024 < 1024)
return $"{fileSize / 1024}KB";
if (fileSize / (1024 * 1024) < 1024)
return $"{fileSize / (1024 * 1024)}MB";
else
return $"{fileSize / (1024 * 1024 * 1024)}GB";
}
#endregion 私有函数
}
}