You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
4.7 KiB

2 years ago
  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Web;
  5. /// <summary>
  6. /// UploadHandler 的摘要说明
  7. /// </summary>
  8. public class UploadHandler : Handler
  9. {
  10. public UploadConfig UploadConfig { get; private set; }
  11. public UploadResult Result { get; private set; }
  12. public UploadHandler(HttpContext context, UploadConfig config)
  13. : base(context)
  14. {
  15. this.UploadConfig = config;
  16. this.Result = new UploadResult() { State = UploadState.Unknown };
  17. }
  18. public override void Process()
  19. {
  20. byte[] uploadFileBytes = null;
  21. string uploadFileName = null;
  22. if (UploadConfig.Base64)
  23. {
  24. uploadFileName = UploadConfig.Base64Filename;
  25. uploadFileBytes = Convert.FromBase64String(Request[UploadConfig.UploadFieldName]);
  26. }
  27. else
  28. {
  29. var file = Request.Files[UploadConfig.UploadFieldName];
  30. uploadFileName = file.FileName;
  31. if (!CheckFileType(uploadFileName))
  32. {
  33. Result.State = UploadState.TypeNotAllow;
  34. WriteResult();
  35. return;
  36. }
  37. if (!CheckFileSize(file.ContentLength))
  38. {
  39. Result.State = UploadState.SizeLimitExceed;
  40. WriteResult();
  41. return;
  42. }
  43. uploadFileBytes = new byte[file.ContentLength];
  44. try
  45. {
  46. file.InputStream.Read(uploadFileBytes, 0, file.ContentLength);
  47. }
  48. catch (Exception)
  49. {
  50. Result.State = UploadState.NetworkError;
  51. WriteResult();
  52. }
  53. }
  54. Result.OriginFileName = uploadFileName;
  55. var savePath = PathFormatter.Format(uploadFileName, UploadConfig.PathFormat);
  56. var localPath = Server.MapPath(savePath);
  57. try
  58. {
  59. if (!Directory.Exists(Path.GetDirectoryName(localPath)))
  60. {
  61. Directory.CreateDirectory(Path.GetDirectoryName(localPath));
  62. }
  63. File.WriteAllBytes(localPath, uploadFileBytes);
  64. Result.Url = savePath;
  65. Result.State = UploadState.Success;
  66. }
  67. catch (Exception e)
  68. {
  69. Result.State = UploadState.FileAccessError;
  70. Result.ErrorMessage = e.Message;
  71. }
  72. finally
  73. {
  74. WriteResult();
  75. }
  76. }
  77. private void WriteResult()
  78. {
  79. this.WriteJson(new
  80. {
  81. state = GetStateMessage(Result.State),
  82. url = Result.Url,
  83. title = Result.OriginFileName,
  84. original = Result.OriginFileName,
  85. error = Result.ErrorMessage
  86. });
  87. }
  88. private string GetStateMessage(UploadState state)
  89. {
  90. switch (state)
  91. {
  92. case UploadState.Success:
  93. return "SUCCESS";
  94. case UploadState.FileAccessError:
  95. return "文件访问出错,请检查写入权限";
  96. case UploadState.SizeLimitExceed:
  97. return "文件大小超出服务器限制";
  98. case UploadState.TypeNotAllow:
  99. return "不允许的文件格式";
  100. case UploadState.NetworkError:
  101. return "网络错误";
  102. }
  103. return "未知错误";
  104. }
  105. private bool CheckFileType(string filename)
  106. {
  107. var fileExtension = Path.GetExtension(filename).ToLower();
  108. return UploadConfig.AllowExtensions.Select(x => x.ToLower()).Contains(fileExtension);
  109. }
  110. private bool CheckFileSize(int size)
  111. {
  112. return size < UploadConfig.SizeLimit;
  113. }
  114. }
  115. public class UploadConfig
  116. {
  117. /// <summary>
  118. /// 文件命名规则
  119. /// </summary>
  120. public string PathFormat { get; set; }
  121. /// <summary>
  122. /// 上传表单域名称
  123. /// </summary>
  124. public string UploadFieldName { get; set; }
  125. /// <summary>
  126. /// 上传大小限制
  127. /// </summary>
  128. public int SizeLimit { get; set; }
  129. /// <summary>
  130. /// 上传允许的文件格式
  131. /// </summary>
  132. public string[] AllowExtensions { get; set; }
  133. /// <summary>
  134. /// 文件是否以 Base64 的形式上传
  135. /// </summary>
  136. public bool Base64 { get; set; }
  137. /// <summary>
  138. /// Base64 字符串所表示的文件名
  139. /// </summary>
  140. public string Base64Filename { get; set; }
  141. }
  142. public class UploadResult
  143. {
  144. public UploadState State { get; set; }
  145. public string Url { get; set; }
  146. public string OriginFileName { get; set; }
  147. public string ErrorMessage { get; set; }
  148. }
  149. public enum UploadState
  150. {
  151. Success = 0,
  152. SizeLimitExceed = -1,
  153. TypeNotAllow = -2,
  154. FileAccessError = -3,
  155. NetworkError = -4,
  156. Unknown = 1,
  157. }