using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Rhea.Common; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using System.IO; using ICSharpCode.SharpZipLib.Zip; using Tiger.IBusiness; namespace Tiger.Api.Controllers.Base { /// /// Api自动更新服务 /// [Route("api/[controller]/[action]")] [EnableCors("Any")] [ApiController] public partial class UpgradeController : ControllerBase { /// /// 获取文件列表 /// /// /// [HttpGet] public async Task GetFileListAsync(string path) { var filePath = UpgradeFileSystem.UpgradeRootPath + path; var allFiles = new List(); await Task.Run(() => { if (Directory.Exists(filePath)) { allFiles = new UpgradeFileSystem(new DirectoryInfo(filePath)).ChildNodes; } else if (System.IO.File.Exists(filePath)) { allFiles.Add(new UpgradeFileSystem(new FileInfo(filePath))); } }); return Ok(allFiles); } /// /// 获取文件 /// /// /// [HttpGet] public async Task GetFileAsync(string path) { var filePath = UpgradeFileSystem.UpgradeRootPath + path; if (System.IO.File.Exists(filePath)) { return await GetFileStreamResultAsync(new FileInfo(filePath)); //return await SegmentDownloadFileAsync(new FileInfo(filePath)); } return Ok(null); } /// /// 获取..\AutoUpgrade.exe /// /// /// [HttpGet] public async Task GetAutoUpgradeProgramAsync() { var filePath = UpgradeFileSystem.UpgradeRootPath + "AutoUpgrade.exe"; if (System.IO.File.Exists(filePath)) { return await GetFileStreamResultAsync(new FileInfo(filePath)); } return Ok($"请先把AutoUpgrade.exe放到更新目录的[{UpgradeFileSystem.UpgradeRootPath}]根目录下"); } /// /// 获取..\AutoUpgrade.exe.config /// /// /// [HttpGet] public async Task GetAutoUpgradeConfigAsync() { var filePath = UpgradeFileSystem.UpgradeRootPath + "AutoUpgrade.exe.config"; if (System.IO.File.Exists(filePath)) { return await GetFileStreamResultAsync(new FileInfo(filePath)); } return Ok($"请先把AutoUpgrade.exe.config放到更新目录的[{UpgradeFileSystem.UpgradeRootPath}]根目录下"); } /// /// 上传文件 /// /// /// /// [HttpPost] public JsonResult UploadFile([FromForm] string fileName, [FromForm] string filePath) { var files = Request.Form.Files; var msgResult = new List(); if (files.Count > 0) { foreach (var formFile in files) { var fullPath = $"{filePath}\\{fileName}"; //save using var stream = new FileStream(fullPath, FileMode.Create); formFile.CopyTo(stream); stream.Close(); stream.Dispose(); //unzip var unZipDir = fullPath.Replace(Path.GetFileName(fullPath), "").Trim('\\'); //System.IO.Compression.ZipFile.ExtractToDirectory(fullPath, unZipDir); var isOK = UnZip(fullPath, unZipDir); //delete compress package System.IO.File.Delete(fullPath); msgResult.Add($"【{fileName}】上传成功,{(isOK ? "解压成功" : "解压失败")}"); } } return new JsonResult(msgResult); } #region Function /// /// 获取到文件流结果 /// /// FileInfo文件 /// 返回FileStreamResult private async Task GetFileStreamResultAsync(FileInfo fileInfo) { if (fileInfo == null) return NotFound(); var memoryStream = new MemoryStream(); using (var stream = new FileStream(fileInfo.FullName, FileMode.Open)) { await stream.CopyToAsync(memoryStream); } memoryStream.Seek(0, SeekOrigin.Begin); //文件名必须编码,否则会有特殊字符(如中文)无法在此下载。 string encodeFilename = System.Net.WebUtility.UrlEncode(fileInfo.Name); Response.Headers.Add("Content-Disposition", "attachment; filename=" + encodeFilename); return new FileStreamResult(memoryStream, "application/octet-stream");//文件流方式,指定文件流对应的ContenType。 } /// /// 获取到文件流结果 /// /// FileInfo文件 /// 返回FileStreamResult private IActionResult GetFileStreamResult(FileInfo fileInfo) { if (fileInfo == null) return NotFound(); var memoryStream = new MemoryStream(); using (var stream = new FileStream(fileInfo.FullName, FileMode.Open)) { stream.CopyTo(memoryStream); } memoryStream.Seek(0, SeekOrigin.Begin); //文件名必须编码,否则会有特殊字符(如中文)无法在此下载。 string encodeFilename = System.Net.WebUtility.UrlEncode(fileInfo.Name); Response.Headers.Add("Content-Disposition", "attachment; filename=" + encodeFilename); return new FileStreamResult(memoryStream, "application/octet-stream");//文件流方式,指定文件流对应的ContenType。 } /// /// 异步分段下载数据 /// /// FileInfo文件 /// 返回响应结果 private async Task SegmentDownloadFileAsync(FileInfo fileInfo) { if (fileInfo == null) return NotFound(); int index = 0; using (FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open)) { if (fs.Length <= 0) { return Ok(new { code = -1, msg = "文件尚未处理" }); } int shardSize = 1 * 1024 * 1024;//一次1M int count = (int)(fs.Length / shardSize); if ((fs.Length % shardSize) > 0) { count += 1; } if (index > count - 1) { return Ok(new { code = -1, msg = "无效的下标" }); } fs.Seek(index * shardSize, SeekOrigin.Begin); if (index == count - 1) { //最后一片 = 总长 - (每次片段大小 * 已下载片段个数) shardSize = (int)(fs.Length - (shardSize * index)); } byte[] datas = new byte[shardSize]; await fs.ReadAsync(datas.AsMemory(0, datas.Length)); return File(datas, "application/octet-stream"); } } /// /// 分段下载数据 /// /// FileInfo文件 /// 返回响应结果 private IActionResult SegmentDownloadFile(FileInfo fileInfo) { if (fileInfo == null) return NotFound(); int index = 0; using (FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open)) { if (fs.Length <= 0) { return Ok(new { code = -1, msg = "文件尚未处理" }); } int shardSize = 1 * 1024 * 1024;//一次1M int count = (int)(fs.Length / shardSize); if ((fs.Length % shardSize) > 0) { count += 1; } if (index > count - 1) { return Ok(new { code = -1, msg = "无效的下标" }); } fs.Seek(index * shardSize, SeekOrigin.Begin); if (index == count - 1) { //最后一片 = 总长 - (每次片段大小 * 已下载片段个数) shardSize = (int)(fs.Length - (shardSize * index)); } byte[] datas = new byte[shardSize]; fs.Read(datas, 0, datas.Length); return File(datas, "application/octet-stream"); } } /// /// 功能:解压zip格式的文件。 /// /// 压缩文件路径 /// 解压文件存放路径,为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹 /// 解压是否成功 private bool UnZip(string zipFilePath, string unZipDir) { try { if (zipFilePath == string.Empty) { throw new Exception("压缩文件不能为空!"); } if (!System.IO.File.Exists(zipFilePath)) { throw new FileNotFoundException("压缩文件不存在!"); } //解压文件夹为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹 if (unZipDir == string.Empty) unZipDir = zipFilePath.Replace(Path.GetFileName(zipFilePath), Path.GetFileNameWithoutExtension(zipFilePath)); if (!unZipDir.EndsWith("/")) unZipDir += "/"; if (!Directory.Exists(unZipDir)) Directory.CreateDirectory(unZipDir); using (var s = new ZipInputStream(System.IO.File.OpenRead(zipFilePath))) { ZipEntry theEntry; while ((theEntry = s.GetNextEntry()) != null) { string directoryName = Path.GetDirectoryName(theEntry.Name); string fileName = Path.GetFileName(theEntry.Name); if (!string.IsNullOrEmpty(directoryName)) { Directory.CreateDirectory(unZipDir + directoryName); } if (directoryName != null && !directoryName.EndsWith("/")) { } if (fileName != string.Empty) { using FileStream streamWriter = System.IO.File.Create(unZipDir + theEntry.Name); int size; byte[] data = new byte[2048]; while (true) { size = s.Read(data, 0, data.Length); if (size > 0) { streamWriter.Write(data, 0, size); } else { break; } } } } } return true; } catch (Exception ex) { //_logger.LogError(ex, $"解压zip格式的文件失败:{zipFilePath}"); return false; } } #endregion }//endClass }