using Infrastructure.Extensions; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Minio; using System; using System.Globalization; using System.IO; using System.IO.Compression; using System.Net.Http; using System.Security.Cryptography; using System.Collections.Generic; namespace Infrastructure.Web.Mvc { public class FileController : Controller { private readonly IWebHostEnvironment _host; private readonly IConfiguration _cfg; private readonly IHttpClientFactory _httpClientFactory; public FileController(IWebHostEnvironment host, IConfiguration cfg, IHttpClientFactory httpClientFactory) { this._host = host; this._cfg = cfg; this._httpClientFactory = httpClientFactory; } public IActionResult Upload() { if (Request.Form.Files != null && Request.Form.Files.Count > 0) { var file = Request.Form.Files[0]; var fileserver = this._cfg.GetSection("AppSettings").GetValue("fileserver"); var path = string.Empty; try { if (string.IsNullOrEmpty(fileserver)) { path = UploadLocalServer(file); } else { if (fileserver == "minio") { path = UploadMinIO(file); } } } catch (Exception ex) { return Content(new { error = 3, msg = ex.Message }.ToJson()); } if (string.IsNullOrEmpty(path)) { return Content(new { error = 2, msg = "文件存储失败" }.ToJson()); } return Content(new { error = 0, url = path }.ToJson()); } return Content(new { error = 1, msg = "未选择文件" }.ToJson()); } public IActionResult Json(string value) { return Content(value); } private string UploadLocalServer(IFormFile file) { using Stream stream = file.OpenReadStream(); var ext = GetExtension(file.FileName); var md5 = GetFileNameHash(stream); var phicyPath = Path.Combine(this._host.WebRootPath, "upload"); Directory.CreateDirectory(phicyPath); var name = string.Format(CultureInfo.CurrentCulture, "{0}.{1}", md5, ext); var fullName = Path.Combine(phicyPath, name); if (!System.IO.File.Exists(fullName)) { using (FileStream fs = System.IO.File.Create(fullName)) { file.CopyTo(fs); } if (ext == "zip") { var zipDirectory = Path.Combine(phicyPath, md5); Directory.CreateDirectory(Path.Combine(phicyPath, md5)); ZipFile.ExtractToDirectory(fullName, zipDirectory); } } return $"/upload/{name}"; } private string UploadMinIO(IFormFile file) { using var stream = file.OpenReadStream(); var ext = GetExtension(file.FileName); var md5 = GetFileNameHash(stream); var name = $"{md5}.{ext}"; var endpoint = this._cfg["minio:endpoint"]; var accessKey = this._cfg["minio:accessKey"]; var secretKey = this._cfg["minio:secretKey"]; var bucketName = "upload"; var minio = new MinioClient(endpoint, accessKey, secretKey);//.WithSSL(); bool found = minio.BucketExistsAsync(bucketName).Result; if (!found) { minio.MakeBucketAsync(bucketName); var policyJson = new { Version = "2012-10-17", Statement = new List{ new { Effect="Allow", Principal=new { AWS=new List{"*"} }, Action=new List{"s3:GetBucketLocation", "s3:ListBucket", "s3:ListBucketMultipartUploads"}, Resource="arn:aws:s3:::upload" }, new { Effect= "Allow", Principal=new { AWS=new List{"*"} }, Action=new List{"s3:AbortMultipartUpload", "s3:DeleteObject", "s3:GetObject", "s3:ListMultipartUploadParts", "s3:PutObject"}, Resource=new List{"arn:aws:s3:::upload/*"} } } }; minio.SetPolicyAsync(bucketName, policyJson.ToJson()); } try { var result = minio.StatObjectAsync(bucketName, name).Result; } catch (AggregateException ex) { ex.PrintStack(); stream.Position = 0; minio.PutObjectAsync(bucketName, name, stream, stream.Length); } var path = $"/{bucketName}/{name}"; return $"/dfs{path}"; } #region private private static string GetExtension(string value) { return value.Substring(value.LastIndexOf('.') + 1).ToLower(CultureInfo.CurrentCulture); } private static string GetFileNameHash(Stream input) { using var hashAlg = SHA256.Create(); byte[] hash = hashAlg.ComputeHash(input); return BitConverter.ToString(hash).Replace("-", string.Empty, true, CultureInfo.CurrentCulture).ToLower(CultureInfo.CurrentCulture); } #endregion private } }