123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668 |
- using System;
- using System.Collections.Concurrent;
- using System.Net;
- using System.Net.Http.Headers;
- using System.Text;
- using WingServerCommon.Config;
- using WingServerCommon.Config.Parameters;
- using WingServerCommon.Log;
- namespace WingServerCommon.Interfaces.FileTransfer
- {
- /// <summary>
- /// 封装上传文件接口
- /// </summary>
- public class UploadFile
- {
- private readonly HttpClient _httpClient;
- //其他存储节点
- private List<string> _otherCloudStorageNodes;
- //自动分块大小5M
- private int _autoSliceSizeForUpload = 0;
- /// <summary>
- /// 默认构造
- /// </summary>
- public UploadFile(HttpClient client)
- {
- _httpClient = client;
- _otherCloudStorageNodes = new List<string>();
- }
- /// <summary>
- /// 上传文件
- /// </summary>
- /// <param name="fileName"></param>
- /// <param name="fileData"></param>
- /// <returns></returns>
- public async Task<string> DoUploadFileAsync(string fileName, byte[] fileData, bool isRechristen = true, string fileExtension = "")
- {
- if (_autoSliceSizeForUpload <= 0)
- {
- _autoSliceSizeForUpload = EnvironmentConfigManager.GetParammeter<IntParameter>("Storage", "AutoSliceSizeForUpload").Value * 2;
- if (_autoSliceSizeForUpload <= 0)
- {
- _autoSliceSizeForUpload = 5242880 * 2;
- }
- }
- if (fileData.Length > _autoSliceSizeForUpload)
- {
- var res = await AutoMultiPartUploadFileAsync(fileName, fileData, isRechristen, fileExtension);
- if (res != null)
- {
- return res.Item1;
- }
- else
- {
- return "";
- }
- }
- else
- {
- var resultTuple = await MultiPartUploadAsync(fileName, fileData, isRechristen, fileExtension);
- if (resultTuple == null)
- {
- Logger.WriteLineInfo("Do MultiPartUploadAsync Fail");
- return "";
- }
- var resultUrl = resultTuple.Item1;
- return resultUrl;
- }
- }
- // <summary>
- /// 上传文件, 自动分块并最终合并文件
- /// </summary>
- /// <param name="record"></param>
- /// <param name="dic"></param>
- /// <param name="isRechristen"></param>
- /// <returns></returns>
- public async Task<string> ManualMultiPartUploadFileAsync(FileTransferRecorder record, Dictionary<int, byte[]> dic, bool isRechristen = true)
- {
- if (_autoSliceSizeForUpload <= 0)
- {
- _autoSliceSizeForUpload = EnvironmentConfigManager.GetParammeter<IntParameter>("Storage", "AutoSliceSizeForUpload").Value * 2;
- if (_autoSliceSizeForUpload <= 0)
- {
- _autoSliceSizeForUpload = 5242880 * 2;
- }
- }
- string fileName = record.ObjectName + record.FileExtension;
- var tupleInitResult = await DoInitMulitPartUploadFileAsync(fileName);
- if (tupleInitResult == null)
- {
- Logger.WriteLineInfo("ManualMultiPartUploadFileAsync Do InitMulitPartUploadFile Fail");
- return "";
- }
- var fileUrl = tupleInitResult.Item1;
- if (string.IsNullOrEmpty(tupleInitResult.Item2))
- {
- Logger.WriteLineInfo("ManualMultiPartUploadFileAsync Get Response InitMulitPartUploadFile Fail");
- return "";
- }
- byte[] bytesR = System.Text.Encoding.UTF8.GetBytes(tupleInitResult.Item2.Replace("\\\"","'").Replace("\\r","").Replace("\\n", "").Replace("utf-16", "utf-8"));
- var initResult = SignatureHelper.DeserializeXML<InitiateMultipartUploadResult>(bytesR) ?? new InitiateMultipartUploadResult();
-
- //分块上传
- var dicPart = new Dictionary<int, byte[]>();
- int allIndex = 0;
- int allPartCount = 0;
- foreach (var partDetail in record.PartList)
- {
- var partCount = (int)((dic[partDetail.PartNumber].Length / _autoSliceSizeForUpload) + (dic[partDetail.PartNumber].Length % _autoSliceSizeForUpload > 0 ? 1 : 0));
- if (partDetail.PartNumber == 0)
- {
- allPartCount = partCount;
- }
- var offsetIndex = 0;
- for (var i = 0; i < partCount; i++)
- {
- var tempLength = _autoSliceSizeForUpload;
- if ((partCount - 1) == i)
- {
- //最后一个分片
- tempLength = dic[partDetail.PartNumber].Length - (partCount - 1) * _autoSliceSizeForUpload;
- }
- var tempByte = new byte[tempLength];
- offsetIndex = i * _autoSliceSizeForUpload;
- Array.Copy(dic[partDetail.PartNumber], offsetIndex, tempByte, 0, tempByte.Length);
- allIndex = allPartCount * partDetail.PartNumber + i + 1;
- dicPart.Add(allIndex, tempByte);
- }
- }
- var dicKeys = dicPart.Keys.OrderBy(c => c).ToList();
- //开始分块上传
- var parallelOption = new ParallelOptions() { MaxDegreeOfParallelism = 3 };
- var resultDic = new ConcurrentDictionary<int, PartInfo>();
- Parallel.ForEach(dicKeys, parallelOption, item => {
- var requestParams = new List<KeyValuePair<string, string>>();
- requestParams.Add(
- new KeyValuePair<string, string>("partNumber", item.ToString())
- );
- requestParams.Add(
- new KeyValuePair<string, string>("uploadId", initResult.UploadId)
- );
- var multiResult = MultiPartUploadAsync(fileName, dicPart[item], isRechristen, record.FileExtension, requestParams).GetAwaiter().GetResult();
- if (multiResult != null)
- {
- var tempEntity = new PartInfo()
- {
- PartNumber = item,
- ETag = multiResult.Item2
- };
- resultDic.TryAdd(item, tempEntity);
- }
- });
- //结束上传
- if (resultDic.Count == dicKeys.Count)
- {
- //上传成功
- var completeEntity = new CompleteMultipartUpload();
- foreach (var dicItem in dicKeys)
- {
- completeEntity.Part.Add(resultDic[dicItem]);
- }
- var requestParams = new List<KeyValuePair<string, string>>();
- requestParams.Add(
- new KeyValuePair<string, string>("uploadId", initResult.UploadId)
- );
- var tupleResult = await DoCompleteMulitPartUploadFileAsync(fileName, completeEntity, isRechristen, requestParams);
- if (tupleResult == null || string.IsNullOrEmpty(tupleResult.Item2))
- {
- Logger.WriteLineInfo("ManualMultiPartUploadFileAsync Do CompleteMulitPartUploadFileAsync Fail");
- return null;
- }
- foreach (var partDetail in record.PartList)
- {
- partDetail.IsUploadComplete = true;
- }
- record.Host = tupleResult.Item1.Replace(fileName, "");
- record.IsUploadComplete = true;
- return tupleResult.Item1;
- }
- else
- {
- Logger.WriteLineInfo("ManualMultiPartUploadFileAsync Do MultiPartUploadAsync Complete Fail");
- return null;
- }
- }
- /// <summary>
- /// 自动分块上传,并在服务端自动合并
- /// </summary>
- private async Task<Tuple<string, string>> AutoMultiPartUploadFileAsync(string fileName, byte[] fileData, bool isRechristen = true, string fileExtension = "")
- {
- //自动分段上传
- //1.初始化
- var tupleInitResult = await DoInitMulitPartUploadFileAsync(fileName);
- if (tupleInitResult == null)
- {
- Logger.WriteLineInfo("Do InitMulitPartUploadFile Fail");
- return null;
- }
- var fileUrl = tupleInitResult.Item1;
- if (string.IsNullOrEmpty(tupleInitResult.Item2))
- {
- Logger.WriteLineInfo("Get Response InitMulitPartUploadFile Fail");
- return null;
- }
- byte[] bytesR = System.Text.Encoding.UTF8.GetBytes(tupleInitResult.Item2.Replace("\\\"","'").Replace("\\r","").Replace("\\n", "").Replace("utf-16", "utf-8"));
- var initResult = SignatureHelper.DeserializeXML<InitiateMultipartUploadResult>(bytesR) ?? new InitiateMultipartUploadResult();
- if (string.IsNullOrWhiteSpace(initResult.UploadId) && !string.IsNullOrWhiteSpace(tupleInitResult.Item2))
- {
- initResult = SignatureHelper.DeserializeXML<InitiateMultipartUploadResult>(tupleInitResult.Item2.Replace("\\\"","'").Replace("\\r","").Replace("\\n", "").Replace("utf-16", "utf-8")) ?? new InitiateMultipartUploadResult();
- }
- //分块上传
- var dic = new Dictionary<int, byte[]>();
- var partCount = (int)((fileData.Length / _autoSliceSizeForUpload) + (fileData.Length % _autoSliceSizeForUpload > 0 ? 1 : 0));
- var offsetIndex = 0;
- for (var i = 0; i < partCount; i++)
- {
- var tempLength = _autoSliceSizeForUpload;
- if ((partCount - 1) == i)
- {
- //最后一个分片
- tempLength = fileData.Length - (partCount - 1) * _autoSliceSizeForUpload;
- }
- var tempByte = new byte[tempLength];
- offsetIndex = i * _autoSliceSizeForUpload;
- Array.Copy(fileData, offsetIndex, tempByte, 0, tempByte.Length);
- dic.Add((i + 1), tempByte);
- }
- var dicKeys = dic.Keys.OrderBy(c => c).ToList();
- //开始分块上传
- var parallelOption = new ParallelOptions() { MaxDegreeOfParallelism = 3 };
- var resultDic = new ConcurrentDictionary<int, PartInfo>();
- Parallel.ForEach(dicKeys, parallelOption, item => {
- var requestParams = new List<KeyValuePair<string, string>>();
- requestParams.Add(
- new KeyValuePair<string, string>("partNumber", item.ToString())
- );
- requestParams.Add(
- new KeyValuePair<string, string>("uploadId", initResult.UploadId)
- );
- var multiResult = MultiPartUploadAsync(fileName, dic[item], isRechristen, fileExtension, requestParams).GetAwaiter().GetResult();
- if (multiResult != null)
- {
- var tempEntity = new PartInfo()
- {
- PartNumber = item,
- ETag = multiResult.Item2
- };
- resultDic.TryAdd(item, tempEntity);
- }
- });
- //结束上传
- if (resultDic.Count == dicKeys.Count)
- {
- //上传成功
- var completeEntity = new CompleteMultipartUpload();
- foreach (var dicItem in dicKeys)
- {
- completeEntity.Part.Add(resultDic[dicItem]);
- }
- var requestParams = new List<KeyValuePair<string, string>>();
- requestParams.Add(
- new KeyValuePair<string, string>("uploadId", initResult.UploadId)
- );
- var tupleResult = await DoCompleteMulitPartUploadFileAsync(fileName, completeEntity, isRechristen, requestParams);
- if (tupleResult == null || string.IsNullOrEmpty(tupleInitResult.Item2))
- {
- Logger.WriteLineInfo("Do CompleteMulitPartUploadFileAsync Fail");
- return null;
- }
- return tupleResult;
- }
- else
- {
- Logger.WriteLineInfo("Do MultiPartUploadAsync Complete Fail");
- return null;
- }
- }
- /// <summary>
- /// 分块上传
- /// </summary>
- /// <param name="fileData"></param>
- /// <returns>上传成功的url</returns>
- private async Task<Tuple<string, string>> MultiPartUploadAsync(string fileName, byte[] fileData, bool isRechristen = true, string fileExtension = "", List<KeyValuePair<string, string>> requestParams = null)
- {
- var requestHeads = new Dictionary<string, string>();
- var authTuple = SignatureHelper.GetAuthorizationAsync(fileName, isRechristen, "put", requestParams);
- if (authTuple == null)
- {
- Logger.WriteLineInfo("Create Signature Fail");
- return null;
- }
- requestHeads.Add("Authorization", authTuple.Item1);
- var fileUrl = authTuple.Item2;
- var eTag = "";
- if (requestParams?.Count > 0)
- {
- var stringParamBuilder = new StringBuilder();
- requestParams = requestParams.OrderBy(c => c.Key).ToList();//TODO check
- foreach (var param in requestParams)
- {
- var encodeKey = SignatureHelper.Encode(param.Key);
- var encodeValue = SignatureHelper.Encode(param.Value);
- stringParamBuilder.Append($"{encodeKey}={encodeValue}&");
- }
- var httpParameters = stringParamBuilder.ToString();
- if (!string.IsNullOrEmpty(httpParameters))
- {
- httpParameters = httpParameters.TrimEnd('&');
- fileUrl += "?" + httpParameters;
- }
- }
- using (var request = new HttpRequestMessage())
- {
- var mimeType = FileHelper.GetMimeType(fileExtension);
- var contentType = MediaTypeHeaderValue.Parse("application/octet-stream");
- using (var content = new HttpUploadContent(fileData, contentType))
- {
- request.RequestUri = new Uri(fileUrl);
- request.Method = HttpMethod.Put;
- request.Content = content;
- foreach (var head in requestHeads)
- {
- request.Headers.TryAddWithoutValidation(head.Key, head.Value);
- }
- var result = await ExecuteRequestAsync(request);
- if (result == null || !result.Item1 || string.IsNullOrEmpty(result.Item2))
- {
- throw new Exception("Upload file failed!");
- }
- eTag = result.Item2;
- }
- }
- return Tuple.Create<string, string>(fileUrl, eTag);
- }
- /// <summary>
- /// 执行copyfile 操作
- /// </summary>
- /// <param name="sourceFileUrl">源目标文件</param>
- /// <param name="fileName"></param>
- /// <returns></returns>
- public async Task<List<string>> DoCopyFileAsync(string sourceFileUrl, string fileName, string destinationServer = "")
- {
- var resList = new List<string>();
- if (_otherCloudStorageNodes.Count <= 0)
- {
- var otherNodes = EnvironmentConfigManager.GetParammeter<StringParameter>("Storage", "OtherNodes").Value;
- var tempList = SignatureHelper.GetOtherCloudStorageNodeList(otherNodes);
- if (tempList?.Count > 0)
- {
- _otherCloudStorageNodes = tempList;
- }
- }
- if (_otherCloudStorageNodes.Count <= 0)
- {
- Logger.WriteLineInfo("Other Nodes Config Info Error");
- return null;
- }
- //处理原链接
- var newSourceFileUrl = sourceFileUrl.Replace("https://", "").Replace("http://", "");
- //处理copy节点
- var bucketList = new List<string>();
- if (string.IsNullOrEmpty(destinationServer))
- {
- bucketList = _otherCloudStorageNodes;
- }
- else
- {
- bucketList = _otherCloudStorageNodes.FindAll(c => c.Contains(destinationServer));
- }
- if (bucketList?.Count > 0)
- {
- var storageServer = ConfigurationManager.GetParammeter<StringParameter>("Storage", "StorageServer").Value;
- var serverType = storageServer == "VCS" ? StorageServerEnum.Vinno : StorageServerEnum.Tencent;
- foreach (var destinationBucket in bucketList)
- {
- if (sourceFileUrl.Contains(destinationBucket))
- {
- continue;
- }
- //生成签名
- List<KeyValuePair<string, string>> _headers = new List<KeyValuePair<string, string>>()
- {
- new KeyValuePair<string, string>("x-cos-copy-source", newSourceFileUrl),
- new KeyValuePair<string, string>("host", destinationBucket),
- };
- var authorization = SignatureHelper.GetStorageCopyAuthorization(fileName, serverType, _headers);
- var requestHeads = new Dictionary<string, string>();
- requestHeads.Add("Authorization", authorization);
- var destinationUrl = "https://" + destinationBucket + "/" + fileName;
- var result = await CopyFileAsync(destinationUrl, newSourceFileUrl, requestHeads);
- if (result == true)
- {
- resList.Add(destinationUrl);
- }
- }
- }
- return resList;
- }
- /// <summary>
- /// 复制文件
- /// </summary>
- /// <param name="destinationUrl">目标服务器</param>
- /// <param name="sourceFileUrl">源服务器</param>
- /// <param name="heads">签名</param>
- /// <returns>是否成功</returns>
- public async Task<bool> CopyFileAsync(string destinationUrl,string sourceFileUrl, Dictionary<string, string> heads)
- {
- var res = false;
- using (var request = new HttpRequestMessage())
- {
- try
- {
- request.RequestUri = new Uri(destinationUrl);
- request.Method = HttpMethod.Put;
- request.Headers.TryAddWithoutValidation("x-cos-copy-source", sourceFileUrl);
- foreach (var head in heads)
- {
- request.Headers.TryAddWithoutValidation(head.Key, head.Value);
- }
- var result = await ExecuteRequestAsync(request);
- if (result == null || !result.Item1)
- {
- Logger.WriteLineError($"FileTransfer CopyFileAsync fail, destinationUrl: {destinationUrl}, sourceFileUrl: {sourceFileUrl}");
- return false;
- }
- res = result.Item1;
- }
- catch(Exception ex)
- {
- Logger.WriteLineError($"FileTransfer CopyFileAsync error, destinationUrl: {destinationUrl}, sourceFileUrl: {sourceFileUrl}, ex: {ex}");
- }
- }
- return res;
- }
- /// <summary>
- /// 执行请求
- /// </summary>
- /// <param name="httpRequestMessage"></param>
- /// <typeparam name="T"></typeparam>
- /// <returns></returns>
- private async Task<Tuple<bool, string>> ExecuteRequestAsync(HttpRequestMessage httpRequestMessage)
- {
- try
- {
- var response = await _httpClient.SendAsync(httpRequestMessage);
- bool res = false;
- var eTag = "";
- if (response != null && response.StatusCode == HttpStatusCode.OK)
- {
- eTag = response.Headers?.ETag?.Tag ?? string.Empty;
- res = true;
- var resultContent = response.Content.Headers.ContentLength > 0;
- if (resultContent)
- {
- eTag = response.Content.Headers.ContentLength.ToString();
- }
- }
- return Tuple.Create<bool, string>(res, eTag);
- }
- catch (Exception ex)
- {
- throw ex;
- }
- }
- /// <summary>
- /// 初始化分块上传文件
- /// </summary>
- /// <param name="fileName"></param>
- /// <param name="fileData"></param>
- /// <returns></returns>
- public async Task<Tuple<string, string>> DoInitMulitPartUploadFileAsync(string fileName)
- {
- var requestHeads = new Dictionary<string, string>();
- var authTuple = SignatureHelper.GetAuthorizationAsync(fileName, false, "post");
- if (authTuple == null)
- {
- Logger.WriteLineInfo("Create Signature Fail");
- return null;
- }
- requestHeads.Add("Authorization", authTuple.Item1);
- var fileUrl = authTuple.Item2 + "?uploads";
- using (var request = new HttpRequestMessage())
- {
- request.RequestUri = new Uri(fileUrl);
- request.Method = HttpMethod.Post;
- foreach (var head in requestHeads)
- {
- request.Headers.TryAddWithoutValidation(head.Key, head.Value);
- }
- request.Headers.TryAddWithoutValidation("Content-Type","application/x-zip-compressed");
- request.Headers.TryAddWithoutValidation("Content-Length", "0");
- var response = await _httpClient.SendAsync(request);
- if (response != null && response.StatusCode == HttpStatusCode.OK)
- {
- //read response content
- var result = await response.Content.ReadAsStringAsync();
- return Tuple.Create<string, string>(fileUrl, result);
- }
- else
- {
- throw new Exception("Upload file failed!");
- }
- }
- }
- /// <summary>
- /// 初始化分块上传文件
- /// </summary>
- /// <param name="fileName"></param>
- /// <param name="fileData"></param>
- /// <returns></returns>
- public async Task<Tuple<string, string>> DoCompleteMulitPartUploadFileAsync(string fileName, CompleteMultipartUpload xmlUpload, bool isRechristen = true, List<KeyValuePair<string, string>> requestParams = null)
- {
- var requestHeads = new Dictionary<string, string>();
- var mimeType = FileHelper.GetMimeType(".config");
- List<KeyValuePair<string, string>> headers = new List<KeyValuePair<string, string>>();
- headers.Add(
- new KeyValuePair<string, string>("Content-Type", mimeType)
- );
- var authTuple = SignatureHelper.GetAuthorizationAsync(fileName, isRechristen, "post", requestParams, headers, true);
- if (authTuple == null)
- {
- Logger.WriteLineInfo("Create Signature Fail");
- return null;
- }
- requestHeads.Add("Authorization", authTuple.Item1);
- var fileUrl = authTuple.Item2;
- if (requestParams?.Count > 0)
- {
- var stringParamBuilder = new StringBuilder();
- requestParams = requestParams.OrderBy(c => c.Key).ToList();//TODO check
- foreach (var param in requestParams)
- {
- var encodeKey = SignatureHelper.Encode(param.Key);
- var encodeValue = SignatureHelper.Encode(param.Value);
- stringParamBuilder.Append($"{encodeKey}={encodeValue}&");
- }
- var httpParameters = stringParamBuilder.ToString();
- if (!string.IsNullOrEmpty(httpParameters))
- {
- httpParameters = httpParameters.TrimEnd('&');
- fileUrl += "?" + httpParameters;
- }
- }
- var xml = "";
- if (xmlUpload.Part?.Count > 0)
- {
- xml = "<CompleteMultipartUpload>";
- foreach (var partInfo in xmlUpload.Part)
- {
- xml += "<Part>";
- xml += "<PartNumber>" + partInfo.PartNumber + "</PartNumber>";
- xml += "<ETag>" + partInfo.ETag + "</ETag>";
- xml += "</Part>";
- }
- xml += "</CompleteMultipartUpload>";
- }
- if (!string.IsNullOrWhiteSpace(xml)) {
- byte[] bytesR = System.Text.Encoding.UTF8.GetBytes(xml);
- var byteContent = new ByteArrayContent(bytesR);
- byteContent.Headers.ContentType = MediaTypeHeaderValue.Parse(mimeType);
- foreach (var head in requestHeads)
- {
- _httpClient.DefaultRequestHeaders.TryAddWithoutValidation(head.Key, head.Value);
- }
- var response = await _httpClient.PostAsync(fileUrl, byteContent).ConfigureAwait(false);
- if (response != null && response.StatusCode == HttpStatusCode.OK)
- {
- //read response content
- var result = await response.Content.ReadAsStringAsync();
- return Tuple.Create<string, string>(authTuple.Item2, result);
- }
- else
- {
- Logger.WriteLineWarn($"UploadFile DoCompleteMulitPartUploadFileAsync failed, response:{response}");
- throw new Exception("Upload file failed!");
- }
- }
- else
- {
- throw new Exception("Upload Xml Data failed!");
- }
- }
-
- /// <summary>
- /// 下载http请求
- /// </summary>
- /// <param name="requestUrl"></param>
- /// <param name="bytes"></param>
- /// <param name="rangeFrom"></param>
- /// <param name="rangeTo"></param>
- /// <param name="fileSize"></param>
- /// <returns>下载是否成功</returns>
- public async Task<bool> DoHttpRequest(string requestUrl, byte[] bytes, long rangeFrom, long rangeTo, long fileSize)
- {
- try
- {
- using (var downloadRequest = new HttpRequestMessage())
- {
- downloadRequest.RequestUri = new Uri(requestUrl);
- downloadRequest.Method = HttpMethod.Get;
- if (rangeTo > fileSize)
- {
- rangeTo = fileSize;
- }
- downloadRequest.Headers.Range = new RangeHeaderValue(rangeFrom, rangeTo);
- var response = await _httpClient.SendAsync(downloadRequest);
- using (var downloadStream = await GetStreamResult(response))
- {
- if (downloadStream == null)
- {
- return false;
- }
- var readLength = rangeTo - rangeFrom;
- var dataToWrite = new byte[readLength];
- var downloadLength = downloadStream.Read(dataToWrite, 0, (int)readLength);
- Array.Copy(dataToWrite, 0, bytes, rangeFrom, downloadLength);
- }
- }
- }
- catch (Exception ex)
- {
- Logger.WriteLineError($"Download fail, {requestUrl}, {ex}");
- return false;
- }
- GC.Collect();
- return true;
- }
- /// <summary>
- /// 获取文件流
- /// </summary>
- /// <param name="response"></param>
- /// <returns></returns>
- private async Task<Stream> GetStreamResult(HttpResponseMessage response)
- {
- if (response != null && (response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.PartialContent))
- {
- return await response.Content.ReadAsStreamAsync();
- }
- if (response != null && response.StatusCode == HttpStatusCode.Forbidden)
- {
- var resultCode = await response.Content.ReadAsStringAsync();
- if (resultCode.IndexOf("-148671") > -1)
- {
- var fileUrl = response.RequestMessage?.RequestUri?.ToString() ?? string.Empty;
- var request = new HttpRequestMessage();
- request.RequestUri = new Uri($"{fileUrl}?restore");
- request.Method = HttpMethod.Put;
- var responseTask = _httpClient.SendAsync(request);
- responseTask.GetAwaiter().GetResult();
- }
- }
- return null;
- }
- }
- }
|