UploadController.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. using HtmlAgilityPack;
  2. using Masuit.MyBlogs.Core.Common;
  3. using Masuit.MyBlogs.Core.Extensions.UEditor;
  4. using Masuit.MyBlogs.Core.Models.DTO;
  5. using Masuit.MyBlogs.Core.Models.ViewModel;
  6. using Masuit.Tools;
  7. using Masuit.Tools.AspNetCore.Mime;
  8. using Masuit.Tools.AspNetCore.ResumeFileResults.Extensions;
  9. using Masuit.Tools.Core.Net;
  10. using Masuit.Tools.Html;
  11. using Masuit.Tools.Logging;
  12. using Masuit.Tools.Systems;
  13. using Microsoft.AspNetCore.Hosting;
  14. using Microsoft.AspNetCore.Http;
  15. using Microsoft.AspNetCore.Mvc;
  16. using Newtonsoft.Json;
  17. using System;
  18. using System.IO;
  19. using System.Text;
  20. using System.Text.RegularExpressions;
  21. using System.Threading.Tasks;
  22. namespace Masuit.MyBlogs.Core.Controllers
  23. {
  24. /// <summary>
  25. /// 文件上传
  26. /// </summary>
  27. [ApiExplorerSettings(IgnoreApi = true)]
  28. public class UploadController : Controller
  29. {
  30. public IWebHostEnvironment HostEnvironment { get; set; }
  31. public ImagebedClient ImagebedClient { get; set; }
  32. /// <summary>
  33. ///
  34. /// </summary>
  35. /// <param name="data"></param>
  36. /// <param name="isTrue"></param>
  37. /// <param name="message"></param>
  38. /// <returns></returns>
  39. public ActionResult ResultData(object data, bool isTrue = true, string message = "")
  40. {
  41. return Content(JsonConvert.SerializeObject(new
  42. {
  43. Success = isTrue,
  44. Message = message,
  45. Data = data
  46. }, new JsonSerializerSettings
  47. {
  48. MissingMemberHandling = MissingMemberHandling.Ignore
  49. }), "application/json", Encoding.UTF8);
  50. }
  51. #region Word上传转码
  52. /// <summary>
  53. /// 上传Word转码
  54. /// </summary>
  55. /// <returns></returns>
  56. [HttpPost]
  57. public async Task<ActionResult> UploadWord()
  58. {
  59. var files = Request.Form.Files;
  60. if (files.Count <= 0)
  61. {
  62. return ResultData(null, false, "请先选择您需要上传的文件!");
  63. }
  64. var file = files[0];
  65. string fileName = file.FileName;
  66. if (!Regex.IsMatch(Path.GetExtension(fileName), "doc|docx"))
  67. {
  68. return ResultData(null, false, "文件格式不支持,只能上传doc或者docx的文档!");
  69. }
  70. await using var ms = file.OpenReadStream().SaveAsMemoryStream();
  71. var html = await SaveAsHtml(ms, file);
  72. if (html.Length < 10)
  73. {
  74. return ResultData(null, false, "读取文件内容失败,请检查文件的完整性,建议另存后重新上传!");
  75. }
  76. if (html.Length > 1000000)
  77. {
  78. return ResultData(null, false, "文档内容超长,服务器拒绝接收,请优化文档内容后再尝试重新上传!");
  79. }
  80. return ResultData(new
  81. {
  82. Title = Path.GetFileNameWithoutExtension(fileName),
  83. Content = html
  84. });
  85. }
  86. private async Task<string> SaveAsHtml(MemoryStream ms, IFormFile file)
  87. {
  88. var html = DocxToHtml.Docx.ConvertToHtml(ms);
  89. var doc = new HtmlDocument();
  90. doc.LoadHtml(html);
  91. var body = doc.DocumentNode.SelectSingleNode("//body");
  92. var style = doc.DocumentNode.SelectSingleNode("//style");
  93. var nodes = body.SelectNodes("//img");
  94. if (nodes != null)
  95. {
  96. foreach (var img in nodes)
  97. {
  98. var attr = img.Attributes["src"].Value;
  99. var strs = attr.Split(",");
  100. var base64 = strs[1];
  101. var bytes = Convert.FromBase64String(base64);
  102. var ext = strs[0].Split(";")[0].Split("/")[1];
  103. await using var image = new MemoryStream(bytes);
  104. var imgFile = $"{SnowFlake.NewId}.{ext}";
  105. var (url, success) = await ImagebedClient.UploadImage(image, imgFile);
  106. if (success)
  107. {
  108. img.Attributes["src"].Value = url;
  109. }
  110. else
  111. {
  112. var path = Path.Combine(HostEnvironment.WebRootPath, "upload", "images", imgFile);
  113. await SaveFile(file, path);
  114. img.Attributes["src"].Value = path.Substring(HostEnvironment.WebRootPath.Length).Replace("\\", "/");
  115. }
  116. }
  117. }
  118. return style.OuterHtml + body.InnerHtml.HtmlSantinizerStandard().HtmlSantinizerCustom(attributes: new[] { "dir", "lang" });
  119. }
  120. private static async Task SaveFile(IFormFile file, string path)
  121. {
  122. var dir = Path.GetDirectoryName(path);
  123. if (!Directory.Exists(dir))
  124. {
  125. Directory.CreateDirectory(dir);
  126. }
  127. await using var fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);
  128. file.CopyTo(fs);
  129. }
  130. #endregion
  131. /// <summary>
  132. /// 文件下载
  133. /// </summary>
  134. /// <param name="path"></param>
  135. /// <returns></returns>
  136. [Route("download")]
  137. [Route("download/{path}")]
  138. public ActionResult Download(string path)
  139. {
  140. if (string.IsNullOrEmpty(path)) return Content("null");
  141. var file = Path.Combine(HostEnvironment.WebRootPath + "/upload", path.Trim('.', '/', '\\'));
  142. if (System.IO.File.Exists(file))
  143. {
  144. return this.ResumePhysicalFile(file, Path.GetFileName(file));
  145. }
  146. return Content("null");
  147. }
  148. /// <summary>
  149. /// UEditor文件上传处理
  150. /// </summary>
  151. /// <returns></returns>
  152. [Route("fileuploader")]
  153. public ActionResult UeditorFileUploader()
  154. {
  155. UserInfoOutputDto user = HttpContext.Session.Get<UserInfoOutputDto>(SessionKey.UserInfo) ?? new UserInfoOutputDto();
  156. Handler action = new NotSupportedHandler(HttpContext);
  157. switch (Request.Query["action"])//通用
  158. {
  159. case "config":
  160. action = new ConfigHandler(HttpContext);
  161. break;
  162. case "uploadimage":
  163. action = new UploadHandler(HttpContext, new UploadConfig()
  164. {
  165. AllowExtensions = UeditorConfig.GetStringList("imageAllowFiles"),
  166. PathFormat = UeditorConfig.GetString("imagePathFormat"),
  167. SizeLimit = UeditorConfig.GetInt("imageMaxSize"),
  168. UploadFieldName = UeditorConfig.GetString("imageFieldName")
  169. });
  170. break;
  171. case "uploadscrawl":
  172. action = new UploadHandler(HttpContext, new UploadConfig()
  173. {
  174. AllowExtensions = new[] { ".png" },
  175. PathFormat = UeditorConfig.GetString("scrawlPathFormat"),
  176. SizeLimit = UeditorConfig.GetInt("scrawlMaxSize"),
  177. UploadFieldName = UeditorConfig.GetString("scrawlFieldName"),
  178. Base64 = true,
  179. Base64Filename = "scrawl.png"
  180. });
  181. break;
  182. case "catchimage":
  183. action = new CrawlerHandler(HttpContext);
  184. break;
  185. }
  186. if (user.IsAdmin)
  187. {
  188. switch (Request.Query["action"])//管理员用
  189. {
  190. //case "uploadvideo":
  191. // action = new UploadHandler(context, new UploadConfig()
  192. // {
  193. // AllowExtensions = UeditorConfig.GetStringList("videoAllowFiles"),
  194. // PathFormat = UeditorConfig.GetString("videoPathFormat"),
  195. // SizeLimit = UeditorConfig.GetInt("videoMaxSize"),
  196. // UploadFieldName = UeditorConfig.GetString("videoFieldName")
  197. // });
  198. // break;
  199. case "uploadfile":
  200. action = new UploadHandler(HttpContext, new UploadConfig()
  201. {
  202. AllowExtensions = UeditorConfig.GetStringList("fileAllowFiles"),
  203. PathFormat = UeditorConfig.GetString("filePathFormat"),
  204. SizeLimit = UeditorConfig.GetInt("fileMaxSize"),
  205. UploadFieldName = UeditorConfig.GetString("fileFieldName")
  206. });
  207. break;
  208. //case "listimage":
  209. // action = new ListFileManager(context, UeditorConfig.GetString("imageManagerListPath"), UeditorConfig.GetStringList("imageManagerAllowFiles"));
  210. // break;
  211. //case "listfile":
  212. // action = new ListFileManager(context, UeditorConfig.GetString("fileManagerListPath"), UeditorConfig.GetStringList("fileManagerAllowFiles"));
  213. // break;
  214. }
  215. }
  216. string result = action.Process();
  217. return Content(result, ContentType.Json);
  218. }
  219. /// <summary>
  220. /// 上传文件
  221. /// </summary>
  222. /// <param name="file"></param>
  223. /// <returns></returns>
  224. [HttpPost("upload"), ApiExplorerSettings(IgnoreApi = false)]
  225. public async Task<ActionResult> UploadFile(IFormFile file)
  226. {
  227. string path;
  228. string filename = SnowFlake.GetInstance().GetUniqueId() + Path.GetExtension(file.FileName);
  229. switch (file.ContentType)
  230. {
  231. case var _ when file.ContentType.StartsWith("image"):
  232. var (url, success) = await ImagebedClient.UploadImage(file.OpenReadStream(), file.FileName);
  233. if (success)
  234. {
  235. return ResultData(url);
  236. }
  237. path = Path.Combine(HostEnvironment.WebRootPath, "upload", "images", filename);
  238. var dir = Path.GetDirectoryName(path);
  239. if (!Directory.Exists(dir))
  240. {
  241. Directory.CreateDirectory(dir);
  242. }
  243. await using (var fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
  244. {
  245. file.CopyTo(fs);
  246. }
  247. break;
  248. case var _ when file.ContentType.StartsWith("audio") || file.ContentType.StartsWith("video"):
  249. path = Path.Combine(HostEnvironment.WebRootPath, "upload", "media", filename);
  250. break;
  251. case var _ when file.ContentType.StartsWith("text") || (ContentType.Doc + "," + ContentType.Xls + "," + ContentType.Ppt + "," + ContentType.Pdf).Contains(file.ContentType):
  252. path = Path.Combine(HostEnvironment.WebRootPath, "upload", "docs", filename);
  253. break;
  254. default:
  255. path = Path.Combine(HostEnvironment.WebRootPath, "upload", "files", filename);
  256. break;
  257. }
  258. try
  259. {
  260. await SaveFile(file, path);
  261. return ResultData(path.Substring(HostEnvironment.WebRootPath.Length).Replace("\\", "/"));
  262. }
  263. catch (Exception e)
  264. {
  265. LogManager.Error(e);
  266. return ResultData(null, false, "文件上传失败!");
  267. }
  268. }
  269. }
  270. }