using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using Vinno.IUS.Common.Log; using Vinno.vCloud.Common.FIS.Storages; using Vinno.vCloud.Common.Storage.ObjectStorageInfo; namespace Vinno.vCloud.Common.FIS.Helper { internal class UploadFileHelper { /// 上传文件 /// /// /// /// public static Tuple UploadFile(string requestUrl, byte[] fileData, string mimeType, string authorization, Action progressCallback = null, CancellationTokenSource cancelTokenSource = null) { var contentType = MediaTypeHeaderValue.Parse(mimeType); var requestHeads = new Dictionary(); ProductInfoHeaderValue productInfoHeaderValue = null; requestHeads.Add("Authorization", authorization); return UploadFile(fileData, contentType, requestUrl, requestHeads, productInfoHeaderValue, progressCallback, cancelTokenSource); } /// /// 上传文件 /// /// /// /// /// /// /// /// public static Tuple UploadFile(string requestUrl, string filePath, string mimeType, string authorization, Action progressCallback = null, CancellationTokenSource cancelTokenSource = null) { var contentType = MediaTypeHeaderValue.Parse(mimeType); var requestHeads = new Dictionary(); ProductInfoHeaderValue productInfoHeaderValue = null; requestHeads.Add("Authorization", authorization); using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { byte[] buffer = new byte[fileStream.Length]; fileStream.Read(buffer, 0, buffer.Length); return UploadFile(buffer, contentType, requestUrl, requestHeads, productInfoHeaderValue, progressCallback, cancelTokenSource); } } /// /// 上传文件(字节流) /// /// /// /// /// /// /// /// /// /// private static Tuple UploadFile(byte[] fileData, MediaTypeHeaderValue mediaTypeHeaderValue, string requestUrl, Dictionary heads, ProductInfoHeaderValue productInfoHeader, Action progressCallback = null, CancellationTokenSource cancelTokenSource = null) { if (fileData == null || fileData.Length == 0) { throw new Exception("FileData is empty"); } using (var request = new HttpRequestMessage()) { using (var content = new UploadContent(fileData, mediaTypeHeaderValue)) { content.ProgressChanged += (sender, progress) => { progressCallback?.Invoke((double)progress / 100); }; request.RequestUri = new Uri(requestUrl); request.Method = HttpMethod.Put; request.Content = content; if (productInfoHeader != null) { request.Headers.UserAgent.Add(productInfoHeader); } foreach (var head in heads) { request.Headers.TryAddWithoutValidation(head.Key, head.Value); } return HttpClientHelper.ExecuteRequest(request, GetUploadResult, false, cancelTokenSource); } } } private static Tuple GetUploadResult(HttpResponseMessage response) { if (response != null && response.StatusCode == HttpStatusCode.OK) { return new Tuple(true, response.Headers?.ETag?.Tag ?? string.Empty); } Logger.WriteLineError($"GetUploadResult Failed, StatusCode: {response?.StatusCode}"); return new Tuple(false, ""); } /// /// 分块读取文件,若文件大于500MB,则每次只读500MB /// internal static FlieSpliceInfo ReadFileData(string filePath, long manualDivisionForUpload, int offsetCount) { bool isReadAllBytes = false; var dic = new Dictionary(); using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { var partCount = (int)((fs.Length / manualDivisionForUpload) + (fs.Length % manualDivisionForUpload > 0 ? 1 : 0)); if (partCount > 1) { var spliceSize = 500 * 1024 * 1024; int spliceCount = 0; if (fs.Length > spliceSize)//每次只读500M { long offsetSize = manualDivisionForUpload * offsetCount; var restSize = fs.Length - offsetSize; if (restSize > spliceSize) { byte[] btArr = new byte[spliceSize]; fs.Seek(offsetSize, SeekOrigin.Begin); fs.Read(btArr, 0, btArr.Length); spliceCount = (int)(spliceSize / manualDivisionForUpload) + (spliceSize % manualDivisionForUpload > 0 ? 1 : 0); long offsetIndex = 0; for (var i = 0; i < spliceCount; i++) { var tempLength = manualDivisionForUpload; var tempByte = new byte[tempLength]; offsetIndex = i * manualDivisionForUpload; Array.Copy(btArr, offsetIndex, tempByte, 0, tempByte.Length); dic.Add(i + offsetCount, tempByte); } } else { byte[] btArr = new byte[restSize]; fs.Seek(offsetSize, SeekOrigin.Begin); fs.Read(btArr, 0, btArr.Length); spliceCount = (int)(restSize / manualDivisionForUpload) + (restSize % manualDivisionForUpload > 0 ? 1 : 0); long offsetIndex = 0; for (var i = 0; i < spliceCount; i++) { var tempLength = manualDivisionForUpload; if (spliceCount - 1 == i) { //最后一个分块File tempLength = btArr.Length - (spliceCount - 1) * manualDivisionForUpload; isReadAllBytes = true; } var tempByte = new byte[tempLength]; offsetIndex = i * manualDivisionForUpload; Array.Copy(btArr, offsetIndex, tempByte, 0, tempByte.Length); dic.Add(i + offsetCount, tempByte); } } } else { //读取文件 byte[] btArr = new byte[fs.Length]; fs.Read(btArr, 0, btArr.Length); if (partCount > 1) { long offsetIndex = 0; for (var i = 0; i < partCount; i++) { var tempLength = manualDivisionForUpload; if (partCount - 1 == i) { //最后一个分块File tempLength = btArr.Length - (partCount - 1) * manualDivisionForUpload; isReadAllBytes = true; } var tempByte = new byte[tempLength]; offsetIndex = i * manualDivisionForUpload; Array.Copy(btArr, offsetIndex, tempByte, 0, tempByte.Length); dic.Add(i, tempByte); } } } } else { byte[] btArr = new byte[fs.Length]; fs.Read(btArr, 0, btArr.Length); dic.Add(0, btArr); isReadAllBytes = true; } return new FlieSpliceInfo(partCount, dic, isReadAllBytes); } } /// /// 分块读取文件 /// internal static Dictionary ReadFileData(string filePath, long manualDivisionForUpload) { var dic = new Dictionary(); using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { var partCount = (int)((fs.Length / manualDivisionForUpload) + (fs.Length % manualDivisionForUpload > 0 ? 1 : 0)); //大于1.7G的问题,用分块读取File if (fs.Length > 1782579200) { var byteSize = 10; byte[] buffer = new byte[byteSize * 1024 * 1024];//10M的缓冲byte int fileCursor = 0; int readerCursor = 0; var splitFileTimes = manualDivisionForUpload / buffer.Length + (manualDivisionForUpload % buffer.Length > 0 ? 1 : 0); var fileSplitFileTimes = fs.Length / buffer.Length + (fs.Length % buffer.Length > 0 ? 1 : 0); if (fileSplitFileTimes < splitFileTimes) { splitFileTimes = fileSplitFileTimes; } //超过200就不能读取了,会溢出 if (splitFileTimes > 200) { return dic; } NextFileBegin: using (MemoryStream ms = new MemoryStream()) { int readLength = 0; while ((readLength = fs.Read(buffer, 0, buffer.Length)) > 0) { readerCursor++; ms.Write(buffer, 0, readLength); if (readerCursor >= splitFileTimes) { var allBytes = ms.ToArray(); dic.Add(fileCursor, allBytes); readerCursor = 0; fileCursor++; break; } else { if (readLength < buffer.Length && readerCursor > 0 && readerCursor < splitFileTimes) { //表示最后一个了 var allBytes = ms.ToArray(); dic.Add(fileCursor, allBytes); readerCursor = 0; fileCursor++; break; } } } } if (fileCursor < partCount) { goto NextFileBegin; } } else { //读取文件 byte[] btArr = new byte[fs.Length]; fs.Read(btArr, 0, btArr.Length); if (partCount > 1) { long offsetIndex = 0; for (var i = 0; i < partCount; i++) { var tempLength = manualDivisionForUpload; if (partCount - 1 == i) { //最后一个分块File tempLength = btArr.Length - (partCount - 1) * manualDivisionForUpload; } var tempByte = new byte[tempLength]; offsetIndex = i * manualDivisionForUpload; Array.Copy(btArr, offsetIndex, tempByte, 0, tempByte.Length); dic.Add(i, tempByte); } } else { dic.Add(0, btArr); } } } return dic; } } }