AttachFilesController.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. using Microsoft.AspNetCore.Hosting;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.AspNetCore.Mvc;
  4. using Microsoft.Extensions.Logging;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.IO;
  8. using System.Linq;
  9. using System.Net;
  10. using System.Threading.Tasks;
  11. using wispro.sp.share;
  12. namespace wispro.sp.api.Controllers
  13. {
  14. [Route("api/[controller]/[action]")]
  15. [ApiController]
  16. public class AttachFilesController : ControllerBase
  17. {
  18. private readonly IWebHostEnvironment env;
  19. private readonly ILogger<AttachFilesController> logger;
  20. public AttachFilesController(IWebHostEnvironment env,
  21. ILogger<AttachFilesController> logger)
  22. {
  23. this.env = env;
  24. this.logger = logger;
  25. }
  26. [HttpPost]
  27. public async Task<ActionResult<IList<UploadResult>>> PostFile(
  28. [FromForm] IEnumerable<IFormFile> files)
  29. {
  30. var maxAllowedFiles = 3;
  31. long maxFileSize = 1024 * 1024 * 15;
  32. var filesProcessed = 0;
  33. var resourcePath = new Uri($"{Request.Scheme}://{Request.Host}/");
  34. List<UploadResult> uploadResults = new();
  35. foreach (var file in files)
  36. {
  37. var uploadResult = new UploadResult();
  38. string trustedFileNameForFileStorage;
  39. var untrustedFileName = file.FileName;
  40. uploadResult.FileName = untrustedFileName;
  41. var trustedFileNameForDisplay =
  42. WebUtility.HtmlEncode(untrustedFileName);
  43. if (filesProcessed < maxAllowedFiles)
  44. {
  45. if (file.Length == 0)
  46. {
  47. logger.LogInformation("{FileName} length is 0 (Err: 1)",
  48. trustedFileNameForDisplay);
  49. uploadResult.ErrorCode = 1;
  50. }
  51. else if (file.Length > maxFileSize)
  52. {
  53. logger.LogInformation("{FileName} of {Length} bytes is " +
  54. "larger than the limit of {Limit} bytes (Err: 2)",
  55. trustedFileNameForDisplay, file.Length, maxFileSize);
  56. uploadResult.ErrorCode = 2;
  57. }
  58. else
  59. {
  60. try
  61. {
  62. trustedFileNameForFileStorage = Path.GetRandomFileName();
  63. var path = Path.Combine(env.ContentRootPath,
  64. env.EnvironmentName, "unsafe_uploads",
  65. trustedFileNameForFileStorage);
  66. await using FileStream fs = new(path, FileMode.Create);
  67. await file.CopyToAsync(fs);
  68. logger.LogInformation("{FileName} saved at {Path}",
  69. trustedFileNameForDisplay, path);
  70. uploadResult.Uploaded = true;
  71. uploadResult.StoredFileName = trustedFileNameForFileStorage;
  72. }
  73. catch (IOException ex)
  74. {
  75. logger.LogError("{FileName} error on upload (Err: 3): {Message}",
  76. trustedFileNameForDisplay, ex.Message);
  77. uploadResult.ErrorCode = 3;
  78. }
  79. }
  80. filesProcessed++;
  81. }
  82. else
  83. {
  84. logger.LogInformation("{FileName} not uploaded because the " +
  85. "request exceeded the allowed {Count} of files (Err: 4)",
  86. trustedFileNameForDisplay, maxAllowedFiles);
  87. uploadResult.ErrorCode = 4;
  88. }
  89. uploadResults.Add(uploadResult);
  90. }
  91. return new CreatedResult(resourcePath, uploadResults);
  92. }
  93. }
  94. }