public static async Task <FormValueProvider> StreamFilesModel(this HttpRequest request, Func <IFormFile, Task> func) { if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType)) { throw new Exception($"Expected a multipart request, but got {request.ContentType}"); } // Used to accumulate all the form url encoded key value pairs in the request. var formAccumulator = new KeyValueAccumulator(); var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, request.Body); var section = await reader.ReadNextSectionAsync(); while (section != null) { var hasHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out ContentDispositionHeaderValue contentDispositionHeader); if (hasHeader && contentDispositionHeader.IsFileDisposition()) { FileMultipartSection fileSection = section.AsFileSection(); // process file stream await func(new MultipartFile(fileSection.FileStream, fileSection.Name, fileSection.FileName) { ContentType = fileSection.Section.ContentType, ContentDisposition = fileSection.Section.ContentDisposition }); } else if (hasHeader && contentDispositionHeader.IsFormDisposition()) { // Content-Disposition: form-data; name="key" // Do not limit the key name length here because the multipart headers length limit is already in effect. var key = HeaderUtilities.RemoveQuotes(contentDispositionHeader.Name); var encoding = section.GetEncoding(); using (var streamReader = new StreamReader(section.Body, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true)) { // The value length limit is enforced by MultipartBodyLengthLimit var value = await streamReader.ReadToEndAsync(); if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase)) { value = String.Empty; } formAccumulator.Append(key.Value, value); if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit) { throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded."); } } } // Drains any remaining section body that has not been consumed and reads the headers for the next section. section = request.Body.CanSeek && request.Body.Position == request.Body.Length ? null : await reader.ReadNextSectionAsync(); } // Bind form data to a model var formValueProvider = new FormValueProvider(BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture); return(formValueProvider); }
/// <summary> /// extract a file from the form section and saves it /// </summary> /// <param name="fileSection"></param> /// <returns>saved file path</returns> private static async Task <string> SaveFile(FileMultipartSection fileSection, string outputDir) { var invalids = Path.GetInvalidFileNameChars(); var fileName = string.Join("_", fileSection.FileName.Split(invalids, StringSplitOptions.RemoveEmptyEntries)).TrimEnd('.'); var path = Path.Combine(outputDir, fileName); using (var stream = new FileStream(path, FileMode.Append)) await fileSection.FileStream.CopyToAsync(stream); return(path); }
public static FileInfoParam GetFileInfo(FileMultipartSection fileMultipartSection) { FileInfoParam fileInfo = new FileInfoParam() { FileName = fileMultipartSection.FileName, // FileName = $"{Guid.NewGuid().ToString("N")}{Path.GetExtension(fileMultipartSection.FileName)}", Size = fileMultipartSection.FileStream.Length, FileExtion = Path.GetExtension(fileMultipartSection.FileName) }; fileInfo.FileType = GetFileType(fileInfo.FileExtion); return(fileInfo); }
/// <summary> /// 接收文件、保存记录 /// </summary> /// <param name="p_section"></param> /// <returns></returns> async Task <FileDesc> ReceiveFile(FileMultipartSection p_section) { FileDesc desc = new FileDesc(); desc.ID = Kit.NewID; desc.Name = p_section.FileName; if (long.TryParse(_context.Request.Headers["uid"], out var id)) { desc.Uploader = id; } desc.Info = p_section.Name; // 扩展名 int pt = desc.Name.LastIndexOf('.'); string ext = pt > -1 ? desc.Name.Substring(pt).ToLower() : ""; // 根据文件名获取两级目录 string dir = GetDir(desc.Name); desc.Path = Path.Combine(_volume, dir, desc.ID + ext).Replace('\\', '/'); EnsurePathExist(dir); string fullPath = Path.Combine(Cfg.Root, _volume, dir, desc.ID + ext); _result.Add(desc.Path); try { using (var writeStream = File.Create(fullPath)) { // FileStream 类型为 MultipartReaderStream await p_section.FileStream.CopyToAsync(writeStream, _bufferSize, _context.RequestAborted); desc.Size = writeStream.Length; } await _db.Exec("上传文件", desc); } catch { FileInfo fi = new FileInfo(fullPath); if (fi.Exists) { try { fi.Delete(); } catch { } } throw; } return(desc); }
public async Task <IActionResult> Upload() { MediaTypeHeaderValue mediaTypeHeaderValue = MediaTypeHeaderValue.Parse(Request.ContentType); string boundary = HeaderUtilities.RemoveQuotes(mediaTypeHeaderValue.Boundary).ToString(); MultipartReader reader = new MultipartReader(boundary, Request.Body, 64 * 1024); MultipartSection section = await reader.ReadNextSectionAsync(); while (section != null) { ContentDispositionHeaderValue contentDispositionHeaderValue = section.GetContentDispositionHeader(); if (!contentDispositionHeaderValue.IsFileDisposition()) { throw new InvalidOperationException("Only file disposition supported."); } FileMultipartSection fileSection = section.AsFileSection(); int bufferSize = 64 * 1024; string fileName = Path.Combine(_targetFilePath, Path.GetFileName(fileSection.FileName)); using (FileStream targetStream = System.IO.File.Create(fileName, bufferSize)) { await fileSection.FileStream.CopyToAsync(targetStream); _logger.LogInformation($"File uploaded to: {fileName}"); } section = await reader.ReadNextSectionAsync(); } return(Ok()); }
private async Task <IFormCollection> InnerReadFormAsync(CancellationToken cancellationToken) { if (!HasFormContentType) { throw new InvalidOperationException("Incorrect Content-Type: " + _request.ContentType); } cancellationToken.ThrowIfCancellationRequested(); //if (_options.BufferBody) //{ // _request.EnableRewind(_options.MemoryBufferThreshold, _options.BufferBodyLengthLimit); //} FormCollection formFields = null; FormFileCollection files = null; // Some of these code paths use StreamReader which does not support cancellation tokens. using (cancellationToken.Register((state) => ((HttpContext)state).Abort(), _request.HttpContext)) { var contentType = ContentType; // Check the content-type if (HasApplicationFormContentType(contentType)) { var encoding = FilterEncoding(contentType.Encoding); using (var formReader = new FormReader(_request.Body, encoding) { ValueCountLimit = _options.ValueCountLimit, KeyLengthLimit = _options.KeyLengthLimit, ValueLengthLimit = _options.ValueLengthLimit, }) { formFields = new FormCollection(await formReader.ReadFormAsync(cancellationToken)); } } else if (HasMultipartFormContentType(contentType)) { var formAccumulator = new KeyValueAccumulator(); var boundary = GetBoundary(contentType, _options.MultipartBoundaryLengthLimit); var multipartReader = new MultipartReader(boundary, _request.Body) { HeadersCountLimit = _options.MultipartHeadersCountLimit, HeadersLengthLimit = _options.MultipartHeadersLengthLimit, BodyLengthLimit = _options.MultipartBodyLengthLimit, }; var section = await multipartReader.ReadNextSectionAsync(cancellationToken); while (section != null) { // Parse the content disposition here and pass it further to avoid reparsings ContentDispositionHeaderValue contentDisposition; ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition); if (contentDisposition.IsFileDisposition()) { var fileSection = new FileMultipartSection(section, contentDisposition); FormFile file; if (section.Body.CanSeek) { // Find the end await section.Body.ConsumeAsync(cancellationToken); var name = fileSection.Name; var fileName = fileSection.FileName; if (section.BaseStreamOffset.HasValue) { // Relative reference to buffered request body file = new StreamFormFile(_request.Body, section.BaseStreamOffset.Value, section.Body.Length, name, fileName); } else { // Individually buffered file body file = new StreamFormFile(section.Body, 0, section.Body.Length, name, fileName); } file.Headers = new HeaderDictionary(section.Headers); } else { //// Enable buffering for the file if not already done for the full body //section.EnableRewind( // _request.HttpContext.Response.RegisterForDispose, // _options.MemoryBufferThreshold, _options.MultipartBodyLengthLimit); //read all bytes. var bytes = await section.Body.ReadAllBytesAsync(cancellationToken); var name = fileSection.Name; var fileName = fileSection.FileName; if (section.BaseStreamOffset.HasValue) { // Relative reference to buffered request body file = new BufferedFormFile(new ArraySegment <byte>(bytes, (int)section.BaseStreamOffset.Value, (int)section.Body.Length), name, fileName); } else { // Individually buffered file body file = new BufferedFormFile(new ArraySegment <byte>(bytes, 0, (int)section.Body.Length), name, fileName); } file.Headers = new HeaderDictionary(section.Headers); } if (files == null) { files = new FormFileCollection(); } if (files.Count >= _options.ValueCountLimit) { throw new InvalidDataException($"Form value count limit {_options.ValueCountLimit} exceeded."); } files.Add(file); } else if (contentDisposition.IsFormDisposition()) { var formDataSection = new FormMultipartSection(section, contentDisposition); // Content-Disposition: form-data; name="key" // // value // Do not limit the key name length here because the mulipart headers length limit is already in effect. var key = formDataSection.Name; var value = await formDataSection.GetValueAsync(); formAccumulator.Append(key, value); if (formAccumulator.ValueCount > _options.ValueCountLimit) { throw new InvalidDataException($"Form value count limit {_options.ValueCountLimit} exceeded."); } } else { System.Diagnostics.Debug.Assert(false, "Unrecognized content-disposition for this section: " + section.ContentDisposition); } section = await multipartReader.ReadNextSectionAsync(cancellationToken); } if (formAccumulator.HasValues) { formFields = new FormCollection(formAccumulator.GetResults(), files); } } } // Rewind so later readers don't have to. if (_request.Body.CanSeek) { _request.Body.Seek(0, SeekOrigin.Begin); } if (formFields != null) { Form = formFields; } else if (files != null) { Form = new FormCollection(null, files); } else { Form = FormCollection.Empty; } return(Form); }
public static async Task <FormValueProvider> StreamFile(this HttpRequest request, Stream targetStream, string path) { file_name = new List <string>(); if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType)) { throw new Exception($"Expected a multipart request, but got {request.ContentType}"); } // Used to accumulate all the form url encoded key value pairs in the // request. var formAccumulator = new KeyValueAccumulator(); // string targetFilePath = ; string targetFilePath = null; var boundary = MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, request.Body); var section = await reader.ReadNextSectionAsync(); //file_name.Clear(); while (section != null) { ContentDispositionHeaderValue contentDisposition; var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition); string rt = contentDisposition.FileName.ToString(); file_name.Add(rt); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { FileMultipartSection currentFile = section.AsFileSection(); string filePath = Path.Combine(path, currentFile.FileName); using (targetStream = File.Create(filePath)) { await section.Body.CopyToAsync(targetStream).ConfigureAwait(false); } } else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition)) { // Do not limit the key name length here because the // multipart headers length limit is already in effect. var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name); var encoding = GetEncoding(section); using (var streamReader = new StreamReader( section.Body, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true)) { // The value length limit is enforced by MultipartBodyLengthLimit var value = await streamReader.ReadToEndAsync(); if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase)) { value = String.Empty; } formAccumulator.Append(key.Value, value); // For .NET Core <2.0 remove ".Value" from key if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit) { throw new InvalidDataException( $"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded."); } } } } // Drains any remaining section body that has not been consumed and // reads the headers for the next section. section = await reader.ReadNextSectionAsync(); } // Bind form data to a model var formValueProvider = new FormValueProvider( BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture); return(formValueProvider); }
public async Task <ParseBodyAndSavePacketsResult> ParseBodyAndSavePackets(MessageHeaders messageHeaders, HttpRequest request) { var cancellationToken = request.HttpContext.RequestAborted; cancellationToken.ThrowIfCancellationRequested(); var format = messageHeaders.Format ?? TransportConstants.RequestFormDataFormat; string boundary = null; if (format == TransportConstants.RequestFormDataFormat) { int fileSectionBufferSize = 81920; // если данные formdata упорядочены в потоке запроса (бинарные данные должны идти после большинства метаданных о пакете) if (messageHeaders.Hints?.Contains(MessageHints.OrderedFormData) == true) { var indexToPacketDataItem = new Dictionary <int, PacketFormDataItem>(); var indexToPacketBytes = new Dictionary <int, byte[]>(); var indexToConfigurationItem = new Dictionary <int, ConfigurationRequestDataItem>(); if (MediaTypeHeaderValue.TryParse(request.ContentType, out var contentType)) { boundary = HeaderUtilities.GetBoundary(contentType, 70); } var multipartReader = new MultipartReader(boundary, request.Body) { //ValueCountLimit = _options.ValueCountLimit, //KeyLengthLimit = _options.KeyLengthLimit, //ValueLengthLimit = _options.ValueLengthLimit, HeadersCountLimit = int.MaxValue, HeadersLengthLimit = int.MaxValue, BodyLengthLimit = long.MaxValue, }; //PacketFormDataItem current = null; //byte[] currentBytes = null; var agentId = messageHeaders.GetAgentIdData(); var section = await multipartReader.ReadNextSectionAsync(cancellationToken); while (section != null) { // Parse the content disposition here and pass it further to avoid reparsings if (!ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition)) { throw new InvalidDataException("Form section has invalid Content-Disposition value: " + section.ContentDisposition); } if (contentDisposition.IsFileDisposition()) { var fileSection = new FileMultipartSection(section, contentDisposition); var name = fileSection.Name; var fileName = fileSection.FileName; var packetId = fileSection.FileName; var result = GetFormPathDataFromEntry(name); if (result != null && result.Parts.Count == 3 && result.Parts[0] == TransportConstants.FormDataPacketsProp) { if (int.TryParse(result.Parts[1], out var index)) { var item = indexToPacketDataItem[index]; var providerKey = item.ProviderKey; var packetItem = indexToPacketDataItem[index]; if (packetItem.PacketId != packetId) { throw new InvalidDataException($"Incorrect format for form-data message. Section {name} has invalid FileName."); } var bytes = await ReadToEnd(fileSection.FileStream, fileSectionBufferSize, cancellationToken); indexToPacketBytes.Add(index, bytes); } else { throw new InvalidDataException($"Incorrect format for form-data message. Section {name} does not have index suffix."); } } else { throw new InvalidDataException($"Incorrect format for form-data message. Section {name} incorrect."); } } else if (contentDisposition.IsFormDisposition()) { var formDataSection = new FormMultipartSection(section, contentDisposition); // Content-Disposition: form-data; name="key" // // value // Do not limit the key name length here because the multipart headers length limit is already in effect. var key = formDataSection.Name; var value = await formDataSection.GetValueAsync(); var result = GetFormPathDataFromEntry(key); if (result != null && result.Parts.Count == 3 && result.Parts[0] == TransportConstants.FormDataPacketsProp) { if (int.TryParse(result.Parts[1], out var index)) { if (!indexToPacketDataItem.TryGetValue(index, out var dataItem)) { //// сохраняем предыдущий //if (current != null) //{ // await this.packetsStore.AddIfNotExistsPacketPartAsync(agentId, this.CreateAddPacketRequest(current, currentBytes)); //} dataItem = new PacketFormDataItem(); indexToPacketDataItem.Add(index, dataItem); } if (!dataItem.FillProperty(result.Parts[2], value)) { throw new InvalidDataException($"Incorrect format for form-data message. Section {key} incorrect."); } } else { throw new InvalidDataException($"Incorrect format for form-data message. Section {key} does not have index suffix."); } } else if (result != null && result.Parts.Count == 3 && result.Parts[0] == TransportConstants.FormDataConfigurationProp) { if (int.TryParse(result.Parts[1], out var index)) { if (!indexToConfigurationItem.TryGetValue(index, out var dataItem)) { dataItem = new ConfigurationRequestDataItem(); indexToConfigurationItem.Add(index, dataItem); } if (!dataItem.FillProperty(result.Parts[2], value)) { throw new InvalidDataException($"Incorrect format for form-data message. Section {key} incorrect."); } } else { throw new InvalidDataException($"Incorrect format for form-data message. Section {key} does not have index suffix."); } } else { // ignore or throw? } //if (formAccumulator.ValueCount > _options.ValueCountLimit) //{ // throw new InvalidDataException($"Form value count limit {_options.ValueCountLimit} exceeded."); //} } else { System.Diagnostics.Debug.Assert(false, "Unrecognized content-disposition for this section: " + section.ContentDisposition); } section = await multipartReader.ReadNextSectionAsync(cancellationToken); } // сохраняем все var addResult = indexToPacketDataItem.Any() ? await this.packetsStore.AddIfNotExistsPacketsPartsAsync(agentId, indexToPacketDataItem.Select(x => { var bytes = indexToPacketBytes[x.Key]; return(this.CreateAddPacketRequest(agentId, x.Value, bytes)); }).ToList()) : AddAddPacketsPartsResult.EmptyResult(); return(new ParseBodyAndSavePacketsResult { TransferedPackets = indexToPacketDataItem.Values .Select(x => { var fromAddResult = addResult.Results.Single(r => r.Request.PacketId == x.PacketId); return new TransferedPacketResponse { PacketId = x.PacketId, ProviderKey = x.ProviderKey, //AgentIdData = agentId, Result = fromAddResult.Success ? TransferedProcessingResult.Saved : TransferedProcessingResult.Error, StorageToken = fromAddResult.StorageToken, Id = fromAddResult.Id, }; }).ToList(), ConfigurationsStats = indexToConfigurationItem.Values, }); } else { var indexToPacketDataItem = new Dictionary <string, PacketFormDataItem>(); var indexToPacketBytes = new Dictionary <string, byte[]>(); var indexToConfigurationItem = new Dictionary <string, ConfigurationRequestDataItem>(); var agentId = messageHeaders.GetAgentIdData(); foreach (var item in request.Form) { var key = item.Key; var value = item.Value; var result = GetFormPathDataFromEntry(key); if (result != null && result.Parts.Count == 3 && result.Parts[0] == TransportConstants.FormDataPacketsProp) { var index = result.Parts[1]; if (!indexToPacketDataItem.TryGetValue(index, out var dataItem)) { dataItem = new PacketFormDataItem(); indexToPacketDataItem.Add(index, dataItem); } if (!dataItem.FillProperty(result.Parts[2], value)) { throw new InvalidDataException($"Incorrect format for form-data message. Section {key} incorrect."); } } if (result != null && result.Parts.Count == 3 && result.Parts[0] == TransportConstants.FormDataConfigurationProp) { var index = result.Parts[1]; if (!indexToConfigurationItem.TryGetValue(index, out var dataItem)) { dataItem = new ConfigurationRequestDataItem(); indexToConfigurationItem.Add(index, dataItem); } if (!dataItem.FillProperty(result.Parts[2], value)) { throw new InvalidDataException($"Incorrect format for form-data message. Section {key} incorrect."); } } } foreach (var file in request.Form.Files) { var pair = indexToPacketDataItem .FirstOrDefault(x => x.Value.PacketId == file.FileName); if (default(KeyValuePair <string, PacketFormDataItem>).Equals(pair)) { var item = pair.Value; var providerKey = item.ProviderKey; var packetId = item.PacketId; using (var fileStream = file.OpenReadStream()) { var currentBytes = await ReadToEnd(fileStream, fileSectionBufferSize, cancellationToken); indexToPacketBytes.Add(pair.Key, currentBytes); } } } // сохраняем все var addResult = indexToPacketDataItem.Any() ? await this.packetsStore.AddIfNotExistsPacketsPartsAsync(agentId, indexToPacketDataItem.Select(x => { var bytes = indexToPacketBytes[x.Key]; return(this.CreateAddPacketRequest(agentId, x.Value, bytes)); }).ToList()) : AddAddPacketsPartsResult.EmptyResult(); return(new ParseBodyAndSavePacketsResult { TransferedPackets = indexToPacketDataItem.Values .Select(x => { var fromAddResult = addResult.Results .Single(r => r.Request.PacketId == x.PacketId); return new TransferedPacketResponse { PacketId = x.PacketId, ProviderKey = x.ProviderKey, //AgentIdData = agentId, Result = fromAddResult.Success ? TransferedProcessingResult.Saved : TransferedProcessingResult.Error, StorageToken = fromAddResult.StorageToken, Id = fromAddResult.Id, }; }).ToList(), ConfigurationsStats = indexToConfigurationItem.Values, }); } } else { throw new NotSupportedException($"format {format} is not supported"); } }
private async Task <FormCollection> GetMultipartFormCollection(ModificationContext modificationContext) { var formAccumulator = new KeyValueAccumulator(); var multipartReader = new MultipartReader(_originalBoundary, modificationContext.ContentStream) { HeadersCountLimit = _options.Value.FormOptions.MultipartHeadersCountLimit, HeadersLengthLimit = _options.Value.FormOptions.MultipartHeadersLengthLimit, BodyLengthLimit = _options.Value.FormOptions.MultipartBodyLengthLimit, }; var section = await multipartReader.ReadNextSectionAsync(); while (section != null) { ContentDispositionHeaderValue contentDisposition; ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition); if (contentDisposition.IsFileDisposition()) { var fileSection = new FileMultipartSection(section, contentDisposition); await section.Body.DrainAsync(new System.Threading.CancellationToken()); FormFile file; if (contentDisposition.FileName == "\"\"") { file = new FormFile( section.Body, 0, section.Body.Length, fileSection.Name, fileSection.FileName ); } else { file = new FormFile( section.BaseStreamOffset.HasValue ? modificationContext.ContentStream : section.Body, section.BaseStreamOffset.HasValue ? section.BaseStreamOffset.Value : 0, section.Body.Length, fileSection.Name, fileSection.FileName ); } file.Headers = new HeaderDictionary(section.Headers); if (_formFiles == null) { _formFiles = new FormFileCollection(); } if (_formFiles.Count >= _options.Value.FormOptions.ValueCountLimit) { throw new InvalidDataException($"Form value count limit {_options.Value.FormOptions.ValueCountLimit} exceeded."); } _formFiles.Add(file); } else if (contentDisposition.IsFormDisposition()) { var formDataSection = new FormMultipartSection(section, contentDisposition); var value = await formDataSection.GetValueAsync(); formAccumulator.Append(formDataSection.Name, value); if (formAccumulator.ValueCount > _options.Value.FormOptions.ValueCountLimit) { throw new InvalidDataException($"Form value count limit {_options.Value.FormOptions.ValueCountLimit} exceeded."); } } else { throw new InvalidDataException($"Unrecognized content-disposition for this section: {section.ContentDisposition}"); } section = await multipartReader.ReadNextSectionAsync(); } if (formAccumulator.HasValues || _formFiles != null) { return(new FormCollection(formAccumulator.HasValues ? formAccumulator.GetResults() : null, _formFiles)); } else { return(null); } }
public async Task <IActionResult> Upload() { string multipartBoundary = Request.GetMultipartBoundary(); if (string.IsNullOrEmpty(multipartBoundary)) { Response.StatusCode = 400; return(Json(new UploadResult { Succeeded = false, Description = $"Expected a multipart request, but got '{Request.ContentType}'." })); } var formAccumulator = new KeyValueAccumulator(); var reader = new MultipartReader(multipartBoundary, HttpContext.Request.Body); MultipartSection section = await reader.ReadNextSectionAsync(); string fileGuid = Guid.NewGuid().ToString(); string userId = _userManager.GetUserId(HttpContext.User); string fileExtension = string.Empty; while (section != null) { FileMultipartSection fileSection = section.AsFileSection(); if (fileSection != null) { string fileName = fileSection.FileName; fileExtension = Path.GetExtension(fileName); string targetFolderPath = Path.Combine(_hostingEnvironment.WebRootPath, _appSettings.UploadsFolder, userId); string targetFilePath = Path.Combine(_hostingEnvironment.WebRootPath, _appSettings.UploadsFolder, userId, $"{fileGuid}{fileExtension}"); if (!Directory.Exists(targetFolderPath)) { Directory.CreateDirectory(targetFolderPath); } using (var targetStream = System.IO.File.Create(targetFilePath)) { await fileSection.FileStream.CopyToAsync(targetStream); _logger.LogInformation($"Copied the uploaded file '{fileName}' to '{targetFilePath}'."); } } else { FormMultipartSection formSection = section.AsFormDataSection(); if (formSection != null) { string name = formSection.Name; string value = await formSection.GetValueAsync(); formAccumulator.Append(name, value); if (formAccumulator.ValueCount > FormReader.DefaultValueCountLimit) { throw new InvalidDataException($"Form key count limit {FormReader.DefaultValueCountLimit} exceeded."); } } } section = await reader.ReadNextSectionAsync(); } var uploadResult = new UploadResult { Succeeded = true, Description = "File was uploaded successfully", FileUrl = $"{_appSettings.Domain}/{_appSettings.UploadsFolder}/{userId}/{fileGuid}{fileExtension}", FileName = $"{fileGuid}{fileExtension}" }; return(Json(uploadResult)); }