public static async Task <HugeMemoryStream> ProcessStreamedFile( MultipartSection section, ContentDispositionHeaderValue contentDisposition, ModelStateDictionary modelState, string[] permittedExtensions, long sizeLimit) { try { var memoryStream = new HugeMemoryStream(); await section.Body.CopyToAsync(memoryStream); // Check if the file is empty or exceeds the size limit. if (memoryStream.Length == 0) { modelState.AddModelError("Error", "The file is empty."); } else if (memoryStream.Length > sizeLimit) { var megabyteSizeLimit = sizeLimit / 1048576; modelState.AddModelError("Error", $"The file exceeds {megabyteSizeLimit:N1} MB."); } else if (!IsValidFileExtensionAndSignature(contentDisposition.FileName.Value, memoryStream, permittedExtensions)) { modelState.AddModelError("Error", $"The file type isn't permitted or the file's signature doesn't match the file's extension. {Path.GetExtension(contentDisposition.FileName.Value).ToLowerInvariant()}"); } else { if (!IsValidFileExtensionAndSignature(memoryStream, permittedExtensions)) { modelState.AddModelError("Error", $"The file type isn't permitted or the file's signature doesn't match the file's extension. {FindMimeHelpers.GetMimeFromStream(memoryStream)} - {FindMimeHelpers.GetExtensionsFromStream(memoryStream)[0]}"); } return(memoryStream); } } catch (Exception ex) { modelState.AddModelError("Error", $"The upload failed. Please contact the Help Desk for support. Error: {ex.Message}"); modelState.AddModelError("Exception", ex.Message); modelState.AddModelError("StackTrace", ex.StackTrace); } return(new HugeMemoryStream()); }
public async Task <IActionResult> UploadFileStream() { string fileNameFinaliy = ""; try { if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { ModelState.AddModelError("Error", $"The request couldn't be processed (Error -1)."); return(BadRequest(ModelState)); } if (!MultipartRequestHelper.ValidateAntiforgeryToken(Request.Headers)) { ModelState.AddModelError("Error", $"The request couldn't be processed (Error 0)."); return(BadRequest(ModelState)); } var formAccumulator = new KeyValueAccumulator(); var trustedFileNameForDisplay = string.Empty; var streamedFileContent = new HugeMemoryStream(); var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, HttpContext.Request.Body); var section = await reader.ReadNextSectionAsync(); if (section == null) { ModelState.AddModelError("Error", $"The request couldn't be processed (Error 1)."); return(BadRequest(ModelState)); } while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { trustedFileNameForDisplay = WebUtility.HtmlEncode(contentDisposition.FileName.Value); streamedFileContent = await FileHelpers.ProcessStreamedFile(section, contentDisposition, ModelState, _permittedExtensions, _fileSizeLimit); if (!ModelState.IsValid) { return(BadRequest(ModelState)); } } else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition)) { var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name).Value; var encoding = GetEncoding(section); if (encoding == null) { ModelState.AddModelError("Error", $"The request couldn't be processed (Error 2)."); return(BadRequest(ModelState)); } using (var streamReader = new StreamReader( section.Body, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true)) { var value = await streamReader.ReadToEndAsync(); if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase)) { value = string.Empty; } formAccumulator.Append(key, value); if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit) { ModelState.AddModelError("Error", $"The request couldn't be processed (Error 3)."); return(BadRequest(ModelState)); } } } } if (!ModelState.IsValid) { return(BadRequest(ModelState)); } section = await reader.ReadNextSectionAsync(); } // Bind form data to the model var formData = new FormData(); var formValueProvider = new FormValueProvider(BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture); var bindingSuccessful = await TryUpdateModelAsync(formData, prefix : "", valueProvider : formValueProvider); if (!bindingSuccessful) { ModelState.AddModelError("Error", "The request couldn't be processed (Error 5)."); return(BadRequest(ModelState)); } if (string.IsNullOrEmpty(trustedFileNameForDisplay) || streamedFileContent.Length <= 0) { ModelState.AddModelError("Error", "The request couldn't be processed (Error 6)."); return(BadRequest(ModelState)); } if (!ModelState.IsValid) { return(BadRequest(ModelState)); } string trustedFileNameForFileStorage = Path.GetRandomFileName(); fileNameFinaliy = Path.Combine(_targetFilePath, trustedFileNameForFileStorage); string mimeType = FindMimeHelpers.GetMimeFromStream(streamedFileContent); using (var targetStream = System.IO.File.Create(fileNameFinaliy)) { streamedFileContent.CopyTo(targetStream); _logger.LogInformation($"Uploaded file '{trustedFileNameForDisplay}' saved to '{_targetFilePath}' as {trustedFileNameForFileStorage}"); } var model = await SaveInDb(HttpContext.Request.HttpContext.Connection.RemoteIpAddress.ToString(), fileNameFinaliy, trustedFileNameForDisplay, trustedFileNameForFileStorage, streamedFileContent.Length, mimeType); return(new OkObjectResult(model.Hash.Trim().ToLower())); } catch (Exception ex) { if (!string.IsNullOrEmpty(fileNameFinaliy) && System.IO.File.Exists(fileNameFinaliy)) { System.IO.File.Delete(fileNameFinaliy); } ModelState.AddModelError("Error", ex.Message); if (ex.InnerException != null) { ModelState.AddModelError("InnerException", ex.InnerException.Message); } return(BadRequest(ModelState)); } }