The next generation of the Teknik Services. Written in ASP.NET. https://www.teknik.io/
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

UploadAPIv1Controller.cs 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Threading.Tasks;
  6. using Microsoft.AspNetCore.Authorization;
  7. using Microsoft.AspNetCore.Mvc;
  8. using Microsoft.EntityFrameworkCore;
  9. using Microsoft.Extensions.Logging;
  10. using MimeDetective;
  11. using MimeDetective.Extensions;
  12. using nClam;
  13. using Teknik.Areas.API.Controllers;
  14. using Teknik.Areas.API.V1.Models;
  15. using Teknik.Areas.Upload;
  16. using Teknik.Areas.Users.Models;
  17. using Teknik.Areas.Users.Utility;
  18. using Teknik.Configuration;
  19. using Teknik.Data;
  20. using Teknik.Logging;
  21. using Teknik.Utilities;
  22. namespace Teknik.Areas.API.V1.Controllers
  23. {
  24. [Authorize(Policy = "WriteAPI")]
  25. public class UploadAPIv1Controller : APIv1Controller
  26. {
  27. public UploadAPIv1Controller(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
  28. [HttpPost]
  29. [AllowAnonymous]
  30. public async Task<IActionResult> Upload(UploadAPIv1Model model)
  31. {
  32. try
  33. {
  34. if (_config.UploadConfig.UploadEnabled)
  35. {
  36. if (model.file != null)
  37. {
  38. long maxUploadSize = _config.UploadConfig.MaxUploadSize;
  39. if (User.Identity.IsAuthenticated)
  40. {
  41. maxUploadSize = _config.UploadConfig.MaxUploadSizeBasic;
  42. IdentityUserInfo userInfo = await IdentityHelper.GetIdentityUserInfo(_config, User.Identity.Name);
  43. if (userInfo.AccountType == AccountType.Premium)
  44. {
  45. maxUploadSize = _config.UploadConfig.MaxUploadSizePremium;
  46. }
  47. }
  48. else
  49. {
  50. // Non-logged in users are defaulted to 1 day expiration
  51. model.expirationUnit = ExpirationUnit.Days;
  52. model.expirationLength = 1;
  53. }
  54. if (model.file.Length <= maxUploadSize)
  55. {
  56. // convert file to bytes
  57. string fileExt = FileHelper.GetFileExtension(model.file.FileName);
  58. long contentLength = model.file.Length;
  59. // Scan the file to detect a virus
  60. if (_config.UploadConfig.VirusScanEnable)
  61. {
  62. ClamClient clam = new ClamClient(_config.UploadConfig.ClamServer, _config.UploadConfig.ClamPort);
  63. clam.MaxStreamSize = maxUploadSize;
  64. ClamScanResult scanResult = await clam.SendAndScanFileAsync(model.file.OpenReadStream());
  65. switch (scanResult.Result)
  66. {
  67. case ClamScanResults.Clean:
  68. break;
  69. case ClamScanResults.VirusDetected:
  70. return Json(new { error = new { message = string.Format("Virus Detected: {0}. As per our <a href=\"{1}\">Terms of Service</a>, Viruses are not permited.", scanResult.InfectedFiles.First().VirusName, Url.SubRouteUrl("tos", "TOS.Index")) } });
  71. case ClamScanResults.Error:
  72. break;
  73. case ClamScanResults.Unknown:
  74. break;
  75. }
  76. }
  77. // Need to grab the contentType if it's empty
  78. if (string.IsNullOrEmpty(model.contentType))
  79. {
  80. model.contentType = model.file.ContentType;
  81. if (string.IsNullOrEmpty(model.contentType))
  82. {
  83. using (Stream fileStream = model.file.OpenReadStream())
  84. {
  85. fileStream.Seek(0, SeekOrigin.Begin);
  86. FileType fileType = fileStream.GetFileType();
  87. if (fileType != null)
  88. model.contentType = fileType.Mime;
  89. if (string.IsNullOrEmpty(model.contentType))
  90. {
  91. model.contentType = "application/octet-stream";
  92. }
  93. }
  94. }
  95. }
  96. // Check content type restrictions (Only for encrypting server side
  97. if (model.encrypt || !string.IsNullOrEmpty(model.key))
  98. {
  99. if (_config.UploadConfig.RestrictedContentTypes.Contains(model.contentType) || _config.UploadConfig.RestrictedExtensions.Contains(fileExt))
  100. {
  101. return Json(new { error = new { message = "File Type Not Allowed" } });
  102. }
  103. }
  104. // Initialize the key size and block size if empty
  105. if (model.keySize <= 0)
  106. model.keySize = _config.UploadConfig.KeySize;
  107. if (model.blockSize <= 0)
  108. model.blockSize = _config.UploadConfig.BlockSize;
  109. // Save the file data
  110. Upload.Models.Upload upload = UploadHelper.SaveFile(_dbContext, _config, model.file.OpenReadStream(), model.contentType, contentLength, model.encrypt, model.expirationUnit, model.expirationLength, fileExt, model.iv, model.key, model.keySize, model.blockSize);
  111. if (upload != null)
  112. {
  113. string fileKey = upload.Key;
  114. // Associate this with the user if they provided an auth key
  115. if (User.Identity.IsAuthenticated)
  116. {
  117. User foundUser = UserHelper.GetUser(_dbContext, User.Identity.Name);
  118. if (foundUser != null)
  119. {
  120. upload.UserId = foundUser.UserId;
  121. _dbContext.Entry(upload).State = EntityState.Modified;
  122. _dbContext.SaveChanges();
  123. }
  124. }
  125. // Generate delete key only if asked to
  126. if (!model.genDeletionKey)
  127. {
  128. upload.DeleteKey = string.Empty;
  129. _dbContext.Entry(upload).State = EntityState.Modified;
  130. _dbContext.SaveChanges();
  131. }
  132. // remove the key if we don't want to save it
  133. if (!model.saveKey)
  134. {
  135. upload.Key = null;
  136. _dbContext.Entry(upload).State = EntityState.Modified;
  137. _dbContext.SaveChanges();
  138. }
  139. // Pull all the information together
  140. string fullUrl = Url.SubRouteUrl("u", "Upload.Download", new { file = upload.Url });
  141. var returnData = new
  142. {
  143. url = (model.saveKey || string.IsNullOrEmpty(fileKey)) ? fullUrl : fullUrl + "#" + fileKey,
  144. fileName = upload.Url,
  145. contentType = upload.ContentType,
  146. contentLength = upload.ContentLength,
  147. key = fileKey,
  148. keySize = upload.KeySize,
  149. iv = upload.IV,
  150. blockSize = upload.BlockSize,
  151. maxDownloads = upload.MaxDownloads,
  152. expirationDate = upload.ExpireDate,
  153. deletionKey = upload.DeleteKey
  154. };
  155. return Json(new { result = returnData });
  156. }
  157. return Json(new { error = new { message = "Unable to save file" } });
  158. }
  159. else
  160. {
  161. return Json(new { error = new { message = "File Too Large" } });
  162. }
  163. }
  164. return Json(new { error = new { message = "Invalid Upload Request" } });
  165. }
  166. return Json(new { error = new { message = "Uploads are Disabled" } });
  167. }
  168. catch (Exception ex)
  169. {
  170. return Json(new { error = new { message = "Exception: " + ex.Message } });
  171. }
  172. }
  173. }
  174. }