123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- using MiniWebApi.Handler;
- using MiniWebApi.Network;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Net.Http;
- using System.Text;
- using System.Threading.Tasks;
- using Vinno.vCloud.Disk.Database;
- using Vinno.vCloud.Disk.Database.Dto;
- using Vinno.vCloud.Disk.UFile;
- using Vinno.vCloud.Common.Storage.ObjectStorageInfo.Authorization;
- using Vinno.vCloud.Common.Storage.ObjectStorageInfo.Solid;
- using System.Collections.Concurrent;
- using Vinno.IUS.Common.Log;
- using Vinno.vCloud.Protocol.Infrastructures.Storage;
- using Vinno.vCloud.Common.Storage.ObjectStorageInfo;
- using Vinno.vCloud.Disk.Tencent;
- namespace Vinno.vCloud.Disk.Controllers
- {
- [WebApiHandler("Upload")]
- class UploadController : BaseHandler
- {
- private ConcurrentDictionary<string, ConcurrentQueue<int>> _uploadProgressDic = new ConcurrentDictionary<string, ConcurrentQueue<int>>();
- private string _filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TempFiles");
- /// <summary>
- /// 上传文件
- /// </summary>
- /// <param name="context"></param>
- [Post]
- public void UploadFile(WebApiHttpContext context)
- {
- try
- {
- var contentType = context.Request.GetHeader().Get("ContentType");
- var param = context.Request.GetFormDataValues();
- var buffer = param.GetValue<byte[]>("fileData");
- var fileMd5 = param.GetValue<string>("fileMd5");
- var chunk = param.GetValue<string>("chunk");
- SaveFile(buffer, fileMd5, chunk);
- context.Response.Json(new { Success = true, Msg = string.Empty }, true);
- }
- catch (Exception ex)
- {
- FileHelper.AppendWriteFile("Log.txt", ex.Message + "|" + ex.StackTrace);
- context.Response.Json(new { Success = false, Msg = "Fail to upload!" }, true);
- }
- }
- /// <summary>
- /// 保存临时文件
- /// </summary>
- /// <param name="enc"></param>
- /// <param name="boundary"></param>
- /// <param name="inputArg"></param>
- /// <param name="filePath"></param>
- private void SaveFile(byte[] fileData, string fileMd5, string chunk)
- {
- //设置文件路径
- string tempFileName;
- Directory.CreateDirectory(_filePath);
- if (chunk==null)
- {
- tempFileName = Path.Combine(_filePath, fileMd5 + ".zip");
- }
- else
- {
- tempFileName = Path.Combine(_filePath, $"{fileMd5}.{chunk}.temp");
- }
- try
- {
- bool isTempFileAdd = true;
- using (FileStream tempStream = new FileStream(tempFileName, FileMode.OpenOrCreate, FileAccess.Write))
- {
- tempStream.Seek(0, SeekOrigin.Begin);
- if (fileData.Length > 0)
- {
- tempStream.Write(fileData, 0, fileData.Length);
- }
- tempStream.Flush();
- if (tempStream.Length == 0)
- {
- isTempFileAdd = false;
- }
- }
- if (!isTempFileAdd)
- {
- File.Delete(tempFileName);
- }
- }
- catch
- {
- File.Delete(tempFileName);
- }
- }
- /// <summary>
- /// 合并临时文件
- /// </summary>
- /// <param name="fileName"></param>
- /// <param name="fileMd5"></param>
- /// <param name="userName"></param>
- /// <returns></returns>
- [Post]
- public void Merge(WebApiHttpContext context)
- {
- try
- {
- var param = context.GetParams();
- var guid = param.GetValue<string>("guid");
- var fileName = param.GetValue<string>("fileName");
- var fileMd5 = param.GetValue<string>("fileMd5");
- var userName = param.GetValue<string>("userName");
- var currId = param.GetValue<string>("currId");
- var currUser = param.GetValue<string>("currUser");
- var fileSize = param.GetValue<string>("fileSize").ToFloat();
- if (!string.IsNullOrWhiteSpace(fileMd5))
- {
- var files = Directory.GetFiles(_filePath);//获得下面的所有文件
- files = files.Where(path => path.IndexOf(fileMd5, StringComparison.Ordinal) > -1).ToArray();
- if (files.Length > 0)
- {
- bool isHadEmptyFiles = false;
- using (var ms = new MemoryStream())
- {
- var sortedFiles = files.OrderBy(x => x.Length).ThenBy(x => x);
- foreach (var part in sortedFiles)//排一下序,保证从0-N Write
- {
- var bytes = File.ReadAllBytes(part);
- if (bytes.Length == 0)
- {
- File.Delete(part);
- isHadEmptyFiles = true;
- }
- if (!isHadEmptyFiles)
- {
- ms.Write(bytes, 0, bytes.Length);
- }
- }
- ms.Flush();
- if (isHadEmptyFiles)
- {
- throw new Exception("Has empty files!");
- }
- var fileExtension = Path.GetExtension(fileName);
- var mimeType = HttpClientHelper.GetMimeType(fileExtension);
- var fileUrl = CosUploadHelper.UploadFile(ms.ToArray(), fileMd5 + fileExtension, mimeType, f => UploadProgressCallback((int)f, guid));
- var isSuccess = false;
- if (!string.IsNullOrEmpty(fileUrl))
- {
- Task.Run(() =>
- {
- foreach (var part in files)
- {
- File.Delete(part);//删除分块
- }
- });
- FoldersAndFiles foldersAndFiles = new FoldersAndFiles();
- foldersAndFiles.Name = fileName;
- foldersAndFiles.Password = string.Empty;
- foldersAndFiles.Type = 0;
- foldersAndFiles.FileUrl = fileUrl;
- foldersAndFiles.FatherId = currId.ToInt();
- foldersAndFiles.FileMd5 = fileMd5;
- foldersAndFiles.Creater = currUser;
- foldersAndFiles.CreateTime = DateTime.UtcNow;
- foldersAndFiles.FileSize = fileSize;
- isSuccess = SqlExecute.DB.Insert(foldersAndFiles) > 0;
- }
- bool isRemoveQueue = _uploadProgressDic.TryRemove(guid,out _);
- Logger.WriteLineInfo($"Remove queue { (isRemoveQueue ? "success" : "fail") } guid:{guid}");
- context.Response.Json(new { Success = isSuccess, Msg = string.Empty }, true);
- return;
- }
- }
- }
- }
- catch (Exception ex)
- {
- FileHelper.AppendWriteFile("Log.txt", ex.Message + "|" + ex.StackTrace);
- }
- context.Response.Json(new { Success = false, Msg = string.Empty }, true);
- }
- /// <summary>
- /// 检查上传文件Md5
- /// </summary>
- /// <param name="fileMd5"></param>
- /// <returns></returns>
- [Post]
- public void CheckUpload(WebApiHttpContext context)
- {
- var param = context.GetParams();
- var fileMd5 = param.GetValue<string>("fileMd5");
- if (!CheckMd5(fileMd5))
- {
- List<string> filesPath = new List<string>();
- if (Directory.Exists(_filePath))
- {
- var files = Directory.GetFiles(_filePath);//获得下面的所有文件
- files = files.Where(path => path.IndexOf(fileMd5, StringComparison.Ordinal) > -1).ToArray();
- foreach (var file in files)
- {
- var chunk = RegexHelper.MatchSub(file, $"{fileMd5}.([0-9]*).temp");
- filesPath.Add(chunk);
- }
- context.Response.Json(new { Chunks = string.Join(",", filesPath) }, true);
- return;
- }
- context.Response.Json(new { Chunks = string.Empty }, true);
- return;
- }
- context.Response.Json(new { Chunks = "%%%" }, true);
- }
- [Post]
- public void GetUploadProgress(WebApiHttpContext context)
- {
- var param = context.GetParams();
- var guid = param.GetValue<string>("guid");
- if (!string.IsNullOrWhiteSpace(guid))
- {
- var progress = GetProgressValue(guid);
- context.Response.Json(new { Progress = progress }, true);
- return;
- }
- context.Response.Json(new { Progress = 0 }, true);
- }
- private static bool CheckMd5(string fileMd5)
- {
- var data = SqlExecute.DB.Query(SqlExecute.DB.GetMapping<FoldersAndFiles>(), "select * from FoldersAndFiles where FileMd5 like ?", $"{fileMd5}%");
- if (data == null || data.Count == 0)
- {
- return false;
- }
- return true;
- }
- private void UploadProgressCallback(int progress,string guid)
- {
- var queue = _uploadProgressDic.GetValueOrDefault(guid);
- if (queue == null)
- {
- queue = new ConcurrentQueue<int>();
- _uploadProgressDic.TryAdd(guid, queue);
- }
- queue.Enqueue(progress);
- }
- private int GetProgressValue(string guid)
- {
- var queue = _uploadProgressDic.GetValueOrDefault(guid);
- if (queue != null)
- {
- int getTime = queue.Count;
- int progress = 0;
- while (getTime>0)
- {
- queue.TryDequeue(out progress);
- getTime--;
- }
- return progress;
- }
- return 0;
- }
- }
- }
|