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;
}
}
}