public async Task <ImportFormParserResult> ParseImportFormAsync(HttpRequest request, string userId, Func <ImportFormData, IFormCollection, Task <bool> > bindAsyncFunc) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (userId == null) { throw new ArgumentNullException(nameof(userId)); } if (bindAsyncFunc == null) { throw new ArgumentNullException(nameof(bindAsyncFunc)); } if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType)) { return(new ImportFormParserResult($"Expected a multipart request, but got {request.ContentType}")); } var defaultFormOptions = new FormOptions(); var jobInfo = new ImportJobRequestInfo { UserId = userId }; 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 hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { jobInfo.CsvFileName = string.Empty; jobInfo.DatasetId = string.Empty; Log.Information("api/data(POST): Starting conversion job. UserId='{0}', File='{1}'", userId, ""); var csvFileId = await _fileStore.AddFileAsync(section.Body); Log.Information($"Saved the uploaded CSV file '{csvFileId}'"); jobInfo.CsvFileId = csvFileId; } else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition)) { 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.ToString(), 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 = await reader.ReadNextSectionAsync(); } // Bind form data to a model var formData = new ImportFormData(); var bindingSuccessful = await bindAsyncFunc(formData, new FormCollection(formAccumulator.GetResults())); if (!bindingSuccessful) { return(new ImportFormParserResult("Import form data validation failed")); } jobInfo.OwnerId = formData.OwnerId; jobInfo.RepositoryId = formData.RepoId; if (string.IsNullOrEmpty(formData.OwnerId) || string.IsNullOrEmpty(formData.RepoId)) { Log.Error("DataController: POST called with no owner or repo set in FormData"); return(new ImportFormParserResult("No target repository supplied")); } if (formData.Metadata == null) { Log.Error("DataController: POST called with no metadata present in FormData"); return(new ImportFormParserResult("No metadata supplied")); } var parser = new JsonSerializer(); Log.Debug("DataController: Metadata: {0}", formData.Metadata); var metadataObject = parser.Deserialize(new JsonTextReader(new StringReader(formData.Metadata))) as JObject; if (metadataObject == null) { Log.Error( "DataController: Error deserializing metadata as object, unable to create conversion job. Metadata = '{0}'", formData.Metadata); return(new ImportFormParserResult("Metadata badly formatted")); } var datasetIri = metadataObject["url"]?.ToString(); var datasetTitle = metadataObject["dc:title"]?.ToString(); if (string.IsNullOrEmpty(datasetIri)) { Log.Error("DataController: No dataset IRI supplied in metadata."); return(new ImportFormParserResult("No dataset IRI supplied in metadata")); } var datasetId = formData.Filename; var datasetIriSplit = datasetIri.Split("/"); if (datasetIriSplit != null && datasetIriSplit.Length > 1) { datasetId = datasetIriSplit[datasetIriSplit.Length - 1]; } Log.Debug("DataController: datasetIri = '{0}'", datasetIri); jobInfo.DatasetIri = datasetIri; // save CSVW to file storage if (string.IsNullOrEmpty(jobInfo.CsvFileName)) { jobInfo.CsvFileName = formData.Filename; jobInfo.DatasetId = datasetId; } jobInfo.IsPublic = formData.ShowOnHomePage; byte[] byteArray = Encoding.UTF8.GetBytes(formData.Metadata); var metadataStream = new MemoryStream(byteArray); var csvwFileId = await _fileStore.AddFileAsync(metadataStream); jobInfo.CsvmFileId = csvwFileId; jobInfo.OverwriteExistingData = formData.OverwriteExisting; if (formData.SaveAsSchema) { Log.Information("api/data(POST): Saving metadata as template."); var schema = new JObject(new JProperty("dc:title", "Template from " + datasetTitle), new JProperty("metadata", metadataObject)); Log.Information("api/data(POST): Starting schema creation job. UserId='{0}', Repository='{1}'", userId, formData.RepoId); byte[] schemaByteArray = Encoding.UTF8.GetBytes(schema.ToString()); var schemaStream = new MemoryStream(schemaByteArray); var schemaFileId = await _fileStore.AddFileAsync(schemaStream); if (!string.IsNullOrEmpty(schemaFileId)) { Log.Information("api/data(POST): Schema temp file saved: {0}.", schemaFileId); var schemaJobRequest = new SchemaImportJobRequestInfo() { UserId = userId, SchemaFileId = schemaFileId, OwnerId = formData.OwnerId, RepositoryId = formData.RepoId }; return(new ImportFormParserResult(jobInfo, schemaJobRequest, formData.Metadata)); } Log.Error( "api/data(POST): Error saving schema content to temporary file storage, unable to start schema creation job"); } return(new ImportFormParserResult(jobInfo, formData.Metadata)); }
public async Task <IActionResult> Upload() { // Used to accumulate all the form url encoded key value pairs in the // request. var formAccumulator = new KeyValueAccumulator(); string targetFilePath = null; var boundary = MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, HttpContext.Request.Body); var section = await reader.ReadNextSectionAsync(); while (section != null) { ContentDispositionHeaderValue contentDisposition; var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { targetFilePath = Path.GetTempFileName(); using (var targetStream = System.IO.File.Create(targetFilePath)) { await section.Body.CopyToAsync(targetStream); //_logger.LogInformation($"Copied the uploaded file '{targetFilePath}'"); } } else if (MultipartRequestHelper.HasFormDataContentDisposition(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 = HeaderUtilities.RemoveQuotes(contentDisposition.Name).Value; 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); 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); //var bindingSuccessful = await TryUpdateModelAsync(user, prefix: "", // valueProvider: formValueProvider); //if (!bindingSuccessful) //{ // if (!ModelState.IsValid) // { // return BadRequest(ModelState); // } //} return(Json("")); }
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)); }
/// based on microsoft example https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/mvc/models/file-uploads/samples/ /// and large file streaming example https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-5.0#upload-large-files-with-streaming private async Task <FileDto> UploadMultipartContent(Stream requestBody, string?contentType, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); // Check if HttpRequest (Form Data) is a Multipart Content Type if (!MultipartRequestHelper.IsMultipartContentType(contentType)) { throw new InvalidDataException($"Expected a multipart request, but got {contentType}"); } var defaultFormOptions = new FormOptions(); // Create a Collection of KeyValue Pairs. var formAccumulator = new KeyValueAccumulator(); // Determine the Multipart Boundary. var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(contentType), defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, requestBody); var section = await reader.ReadNextSectionAsync(cancellationToken); var fileDto = new FileDto(); // Loop through each 'Section', starting with the current 'Section'. while (section != null) { // Check if the current 'Section' has a ContentDispositionHeader. var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { if (contentDisposition != null) { var sectionFileName = contentDisposition.FileName.Value; // use an encoded filename in case there is anything weird var encodedFileName = WebUtility.HtmlEncode(Path.GetFileName(sectionFileName)); // read the section filename to get the content type var fileExtension = Path.GetExtension(sectionFileName); // now make it unique var uniqueFileName = $"{Guid.NewGuid()}{fileExtension}"; string?md5Hash; // TODO MimeDetective does not work when stream has already been uploaded - figure out a solution //if (fileContentTypeMatchesExtension is false) //{ // await _blobStorageProvider.DeleteFileAsync(uniqueFileName); // _logger.LogError("File extension:{0} does not match the file signature", fileExtension); // throw new FormatException("File extension} does not match the file signature"); //} if (!_acceptedFileTypes.Contains(fileExtension.ToLower())) { _logger.LogError("file extension:{0} is not an accepted file", fileExtension); throw new ConstraintException("The file is not an accepted file"); } try { md5Hash = await _blobStorageProvider.UploadFileAsync(section.Body, uniqueFileName, MimeTypesMap.GetMimeType(encodedFileName), cancellationToken); } catch (Exception ex) { _logger.LogError(ex, "An error occurred uploading file to blob storage"); throw; } // TODO MimeDetective does not work when stream has already been uploaded - figure out a solution //if (fileContentTypeMatchesExtension is false) //{ // await _blobStorageProvider.DeleteFileAsync(uniqueFileName); // _logger.LogError("File extension:{0} does not match the file signature", fileExtension); // throw new FormatException("File extension} does not match the file signature"); //} var now = _systemClock.UtcNow.UtcDateTime; // trick to get the size without reading the stream in memory var size = section.Body.Position; fileDto.FileName = encodedFileName; fileDto.FileExtension = fileExtension; fileDto.FileSizeBytes = size; fileDto.BlobName = uniqueFileName; fileDto.CreatedAtUTC = now; if (md5Hash != null) { fileDto.BlobHash = Convert.FromBase64String(md5Hash); } } } else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition)) { // if for some reason other form data is sent it would get processed here var key = HeaderUtilities.RemoveQuotes(contentDisposition?.Name.ToString().ToLowerInvariant()); var encoding = GetEncoding(section); 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, value); if (formAccumulator.ValueCount > defaultFormOptions.ValueCountLimit) { _logger.LogError("FileUpload: Form key count limit {0} exceeded.", defaultFormOptions.ValueCountLimit); throw new FormatException($"Form key count limit { defaultFormOptions.ValueCountLimit } exceeded."); } } } } // Begin reading the next 'Section' inside the 'Body' of the Request. section = await reader.ReadNextSectionAsync(cancellationToken); } if (formAccumulator.HasValues) { var formValues = formAccumulator.GetResults(); var titleFound = formValues.TryGetValue("title", out var title); if (titleFound is false) { throw new ArgumentNullException($"Title was not provided"); } var descriptionFound = formValues.TryGetValue("description", out var description); if (descriptionFound is false) { throw new ArgumentNullException($"Description was not provided"); } fileDto.Title = title; fileDto.Description = description; } return(fileDto); }
public async Task <IActionResult> Upload() { if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { return(BadRequest($"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, HttpContext.Request.Body); using (_logger.BeginScope(new { Boundary = boundary, Request.ContentType })) { _logger.LogTrace("Reading next section"); var section = await reader.ReadNextSectionAsync(); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { _logger.LogTrace("Content Disposition Header: {0}", section.ContentDisposition); if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { var fileName = contentDisposition.FileName.Value; if (!SubmissionDataFormFileNamesLazy.Value.Contains(contentDisposition.Name.Value)) { _logger.LogInformation($"Unknown file '{contentDisposition.Name.Value}' with fileName: '{fileName}' is being ignored."); // Drains any remaining section body that has not been consumed and // reads the headers for the next section. section = await reader.ReadNextSectionAsync(); continue; } formAccumulator.Append(contentDisposition.Name.Value, fileName); var path = await _tempFileService.CreateFromStreamAsync(fileName, section.Body); _logger.LogInformation($"Copied the uploaded file '{fileName}' to path: '{path}'"); } else if (MultipartRequestHelper.HasFormDataContentDisposition(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 = HeaderUtilities.RemoveQuotes(contentDisposition.Name); _logger.LogDebug("Retrieving value for {0}", key); 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); 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 submissionData = new SubmissionData(); var bindingSuccessful = await BindDataAsync(submissionData, formAccumulator.GetResults()); if (!bindingSuccessful) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } } var requiredFormFileProperties = typeof(SubmissionData).GetProperties() .Where(p => p.GetCustomAttributes(typeof(RequiredAttribute), true).Any()) .Where(p => p.GetCustomAttributes(typeof(FormFileAttribute), true).Any()); foreach (var requiredFormFileProperty in requiredFormFileProperties) { var fileName = requiredFormFileProperty.GetValue(submissionData); if (!_tempFileService.Files.Contains(fileName)) { ModelState.AddModelError(requiredFormFileProperty.Name, $"File '{requiredFormFileProperty.Name}' with name: '{fileName}' not found in request."); return(BadRequest(ModelState)); } } var repositoryOwner = User.Claims.FirstOrDefault(c => c.Type == "urn:msbloc:repositoryOwner")?.Value; var repositoryName = User.Claims.FirstOrDefault(c => c.Type == "urn:msbloc:repositoryName")?.Value; var checkRun = await _logAnalyzerService.SubmitAsync( repositoryOwner, repositoryName, submissionData.CommitSha, submissionData.CloneRoot, _tempFileService.GetFilePath(submissionData.BinaryLogFile)); return(Json(checkRun)); }
public static async Task <HttpResponseUploadModel> StreamFileToAzureBlobStorage(this HttpRequest request, string folder, CloudStorageAccount blobAccount, FormOptions _defaultFormOptions, List <string> logDetails) { // Setup Azure Blob Storage CloudBlobClient blobClient = blobAccount.CreateCloudBlobClient(); CloudBlobContainer container = blobClient.GetContainerReference(folder); CloudBlockBlob blockBlob = null; // Check if HttpRequest (Form Data) is a Multipart Content Type if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType)) { Console.WriteLine($"****: Expected a multipart request, but got { request.ContentType}"); throw new Exception($"Expected a multipart request, but got {request.ContentType}"); } else { Console.WriteLine($"****: Received a multipart Request.ContentType: { request.ContentType}"); } // Create a Collection of KeyValue Pairs. var formAccumulator = new KeyValueAccumulator(); // Determine the Multipart Boundary. var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); // Setup a Multipart Reader using the determined 'Section Boundary' and the 'Body' of the HttpRequest. var reader = new MultipartReader(boundary, request.Body); // Read the next Multipart Section inside the 'Body' of the Request. Console.Write("****: Begin Read of Section: " + DateTime.Now.ToString()); logDetails.Add("****: Begin Read of Section: " + DateTime.Now.ToString()); var section = await reader.ReadNextSectionAsync(); Console.Write("****: End Read of Section: " + DateTime.Now.ToString()); logDetails.Add("****: End Read of Section: " + DateTime.Now.ToString()); Console.WriteLine("****: Current Multipart Section Size: " + section.Body.Length.ToString()); // Loop through each 'Section', starting with the current 'Section'. while (section != null) { // Check if the current 'Section' has a ContentDispositionHeader. var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out ContentDispositionHeaderValue contentDisposition); //var disposition = ContentDispositionHeaderValue.Parse(section.ContentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { try { string fileName = System.Web.HttpUtility.UrlEncode(contentDisposition.FileName.Value.Replace("\"", ""), Encoding.UTF8); blockBlob = container.GetBlockBlobReference(string.Format("{0}{1}", Guid.NewGuid().ToString(), Path.GetExtension(fileName))); blockBlob.Properties.ContentType = MimeTypeHelper.GetMimeType(fileName); blockBlob.Metadata.Add("LocalFileName", fileName); blockBlob.Metadata.Add("TenantID", "136af1ab-dce8-458f-af5c-1c7bd2711dd3"); //TODO: Revise comment here. blockBlob.Properties.ContentDisposition = "attachment; filename*=UTF-8''" + fileName; // Upload the current 'Section' including properties to Azure Blob Storage. Console.Write("****: Begin Upload of Section to Azure: " + DateTime.Now.ToString() + " : " + fileName); logDetails.Add("****: Begin Upload of Section to Azure: " + DateTime.Now.ToString() + " : " + fileName); await blockBlob.UploadFromStreamAsync(section.Body); Console.Write("****: End Upload of Section to Azure: " + DateTime.Now.ToString() + " : " + fileName); logDetails.Add("****: End Upload of Section to Azure: " + DateTime.Now.ToString() + " : " + fileName); } catch (Exception e) { Console.WriteLine(e); throw; } } else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition)) { var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name); var encoding = GetEncoding(section); 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, value); if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit) { throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded."); } } } } // Begin reading the next 'Section' inside the 'Body' of the Request. Console.Write("****: Begin Read of Section: " + DateTime.Now.ToString()); logDetails.Add("****: Begin Read of Section: " + DateTime.Now.ToString()); section = await reader.ReadNextSectionAsync(); Console.Write("****: End Read of Section: " + DateTime.Now.ToString()); logDetails.Add("****: End Read of Section: " + DateTime.Now.ToString()); } var formValueProvider = new FormValueProvider(BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture); return(new HttpResponseUploadModel { FormValueProvider = formValueProvider, Url = blockBlob?.Uri.ToString(), logDetails = logDetails }); }
public async Task <IActionResult> Upload() { if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { return(BadRequest($"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 = null; var boundary = MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, HttpContext.Request.Body); var section = await reader.ReadNextSectionAsync(); while (section != null) { ContentDispositionHeaderValue contentDisposition; ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition); if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { var name = HeaderUtilities.RemoveQuotes(contentDisposition.Name) ?? string.Empty; var fileName = HeaderUtilities.RemoveQuotes(contentDisposition.FileName) ?? string.Empty; // Here the uploaded file is being copied to local disk but you can also for example, copy the // stream directly to let's say Azure blob storage targetFilePath = Path.Combine(_hostingEnvironment.ContentRootPath, Guid.NewGuid().ToString()); using (var targetStream = System.IO.File.Create(targetFilePath)) { await section.Body.CopyToAsync(targetStream); _logger.LogInformation($"Copied the uploaded file '{fileName}' to '{targetFilePath}'."); } } else if (MultipartRequestHelper.HasFormDataContentDisposition(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 = HeaderUtilities.RemoveQuotes(contentDisposition.Name); MediaTypeHeaderValue mediaType; MediaTypeHeaderValue.TryParse(section.ContentType, out mediaType); var encoding = FilterEncoding(mediaType?.Encoding); 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(); formAccumulator.Append(key, 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 = await reader.ReadNextSectionAsync(); } // Bind form data to a model var user = new User(); var formValueProvider = new FormValueProvider( BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture); var bindingSuccessful = await TryUpdateModelAsync(user, prefix : "", valueProvider : formValueProvider); if (!bindingSuccessful) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } } var uploadedData = new UploadedData() { Name = user.Name, Age = user.Age, Zipcode = user.Zipcode, FilePath = targetFilePath }; return(Json(uploadedData)); }
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); // Enable buffering for the file if not already done for the full body section.EnableRewind( _request.HttpContext.Response.RegisterForDispose, _options.MemoryBufferThreshold, _options.MultipartBodyLengthLimit); // Find the end await section.Body.DrainAsync(cancellationToken); var name = fileSection.Name; var fileName = fileSection.FileName; FormFile file; if (section.BaseStreamOffset.HasValue) { // Relative reference to buffered request body file = new FormFile(_request.Body, section.BaseStreamOffset.Value, section.Body.Length, name, fileName); } else { // Individually buffered file body file = new FormFile(section.Body, 0, 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 <UploadResponse> StreamFile(this HttpRequest request, AssetSettings assetSettings) { Guard.AgainstInvalidArgument(nameof(request.ContentType), MultipartRequestHelper.IsMultipartContentType(request.ContentType)); var results = new UploadResponse(); results.Messages = new List <UploadResponseMessage>(); var formAccumulator = new KeyValueAccumulator(); // Used to accumulate all the form url encoded key value pairs in the request. var fileDtos = new List <FileDto>(); 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) { ContentDispositionHeaderValue contentDisposition; var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition); if (hasContentDispositionHeader) { string orginalFileName = contentDisposition.FileName.Value; string fileName = $"{DateTime.Now:yyyyMMddHHmmss}_{orginalFileName}"; string targetFile = Path.Combine(assetSettings.TempDataFolder, fileName); if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { using (var memoryStream = File.Create(targetFile)) { await section.Body.CopyToAsync(memoryStream); if (memoryStream.Length == 0) { results.Messages.Add(new UploadResponseMessage() { Text = $"The file {orginalFileName} is empty.", Code = "FileEmpty" }); } else if (memoryStream.Length > assetSettings.FileSizeLimit) { var megabyteSizeLimit = assetSettings.FileSizeLimit / 1048576; //1MB results.Messages.Add(new UploadResponseMessage() { Text = $"The file {orginalFileName} exceeds limit {megabyteSizeLimit:N1} MB.", Code = "ExceedLimit" }); } else { string extension = Path.GetExtension(targetFile); var fileDto = new FileDto() { OriginalFileName = orginalFileName, FilePath = targetFile, Extension = extension != null?extension.Replace(".", "") : "", FileName = fileName }; // Copy stream to dto would be faster then re-read file from physical disk fileDto.StreamData = new MemoryStream(); memoryStream.Position = 0; await memoryStream.CopyToAsync(fileDto.StreamData); fileDtos.Add(fileDto); } } } else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition)) { // Don't limit the key name length because the multipart headers length limit is already in effect. var key = HeaderUtilities .RemoveQuotes(contentDisposition.Name).Value; 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); } } } // Drains any remaining section body that has not been consumed and // reads the headers for the next section. section = await reader.ReadNextSectionAsync(); } results.Files = fileDtos; results.FormAccumulator = formAccumulator; results.Status = true; results.ErrorCode = ResponseErrorCode.None; results.Message = "Ok"; return(results); }
public async Task <IActionResult> GetUploadStream() { if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { return(BadRequest($"Expected a multipart request, but got {Request.ContentType}")); } //const string contentType = "application/octet-stream"; string boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), FormOptions.DefaultMultipartBoundaryLengthLimit); MultipartReader reader = new MultipartReader(boundary, Request.Body, 80 * 1024); //Dictionary<string, string> sectionDictionary = new Dictionary<string, string>(); //var memoryStream = new MemoryStream(); //MultipartSection section; //while ((section = await reader.ReadNextSectionAsync()) != null) //{ // ContentDispositionHeaderValue contentDispositionHeaderValue = section.GetContentDispositionHeader(); // if (contentDispositionHeaderValue.IsFormDisposition()) // { // FormMultipartSection formMultipartSection = section.AsFormDataSection(); // string value = await formMultipartSection.GetValueAsync(); // sectionDictionary.Add(formMultipartSection.Name, value); // } // else if (contentDispositionHeaderValue.IsFileDisposition()) // { // // we save the file in a temporary stream // var fileMultipartSection = section.AsFileSection(); // await fileMultipartSection.FileStream.CopyToAsync(memoryStream); // memoryStream.Position = 0; // } //} var formAccumulator = new KeyValueAccumulator(); // Used to accumulate all the form url encoded key value pairs in the request. var section = await reader.ReadNextSectionAsync(); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out ContentDispositionHeaderValue contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { //targetFilePath = Path.GetTempFileName(); //using (var targetStream = System.IO.File.Create(targetFilePath)) //{ // await section.Body.CopyToAsync(targetStream); // _logger.LogInformation($"Copied the uploaded file '{targetFilePath}'"); //} } else if (MultipartRequestHelper.HasFormDataContentDisposition(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 = 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); 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(); } //CloudStorageAccount.TryParse(connectionString, out CloudStorageAccount cloudStorageAccount); //CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient(); //CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName); //if (await cloudBlobContainer.CreateIfNotExistsAsync()) //{ // BlobContainerPermissions blobContainerPermission = new BlobContainerPermissions() { PublicAccess = BlobContainerPublicAccessType.Container }; // await cloudBlobContainer.SetPermissionsAsync(blobContainerPermission); //} //MyFile myFile = JsonConvert.DeserializeObject<MyFile>(sectionDictionary.GetValueOrDefault(nameof(MyFile))); //CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(myFile.RelativePath); //using (Stream blobStream = await cloudBlockBlob.OpenWriteAsync()) //{ // // Finally copy the file into the blob writable stream // await memoryStream.CopyToAsync(blobStream); //} //// you can replace OpenWriteAsync by //// await cloudBlockBlob.UploadFromStreamAsync(memoryStream); //CloudBlobContainer vCloudBlobContainer = await GetCloudBlobContainer().ConfigureAwait(false); //MyFile myFile; //while ((section = await reader.ReadNextSectionAsync().ConfigureAwait(false)) != null) //{ // ContentDispositionHeaderValue contentDispositionHeaderValue = section.GetContentDispositionHeader(); // if (contentDispositionHeaderValue.IsFormDisposition()) // { // FormMultipartSection formMultipartSection = section.AsFormDataSection(); // string value = await formMultipartSection.GetValueAsync().ConfigureAwait(false); // sectionDictionary.Add(formMultipartSection.Name, value); // } // else if (contentDispositionHeaderValue.IsFileDisposition()) // { // myFile = JsonConvert.DeserializeObject<MyFile>(sectionDictionary.GetValueOrDefault(nameof(MyFile))); // if (myFile == default(object)) throw new InvalidOperationException(); // CloudBlockBlob cloudBlockBlob = vCloudBlobContainer.GetBlockBlobReference(myFile.RelativePath); // Stream stream = await cloudBlockBlob.OpenWriteAsync().ConfigureAwait(false); // FileMultipartSection fileMultipartSection = section.AsFileSection(); // await cloudBlockBlob.UploadFromStreamAsync(fileMultipartSection.FileStream).ConfigureAwait(false); // } //} return(Ok()); // return httpcode 200 }
public async Task <IActionResult> Upload() { try { if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { return(BadRequest($"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, HttpContext.Request.Body); var targetFileDirectory = Path.Combine(_hostingEnvironment.ContentRootPath, "Uploads"); if (!Directory.Exists(targetFileDirectory)) { Directory.CreateDirectory(targetFileDirectory); } var section = await reader.ReadNextSectionAsync(); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { var fileName = HeaderUtilities.RemoveQuotes(contentDisposition.FileName).Value; var filePath = Path.Combine(targetFileDirectory, fileName); formAccumulator.Append("FileName", fileName); formAccumulator.Append("FilePath", filePath); using (var targetStream = System.IO.File.Create(filePath)) { await section.Body.CopyToAsync(targetStream); _logger.LogInformation($"Copied the uploaded file '{filePath}'"); } } else if (MultipartRequestHelper.HasFormDataContentDisposition(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 = HeaderUtilities.RemoveQuotes(contentDisposition.Name); var encoding = MultipartRequestHelper.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); 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 dataFile = new DataFile(); var formValueProvider = new FormValueProvider( BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture); var bindingSuccessful = await TryUpdateModelAsync(dataFile, prefix : "", valueProvider : formValueProvider); if (!bindingSuccessful) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } } var dataFileId = _context.DataFile .AsNoTracking() .Where(el => el.FileName == dataFile.FileName || el.FilePath == dataFile.FilePath) .Select(el => el.Id) .SingleOrDefault(); if (dataFileId == 0) { _context.DataFile.Add(dataFile); _context.SaveChanges(); dataFileId = dataFile.Id; } else { var df = _context.DataFile.Find(dataFileId); df.FilePath = dataFile.FilePath; df.FileName = dataFile.FileName; } var(lineItems, errorList) = ExcelHelper.ConvertCsVtoDataTable(dataFile.FilePath, dataFileId); var listItems = lineItems; var errors = errorList; System.IO.File.Delete(dataFile.FilePath); if (errors != null && errors.Any()) { var conn = _context.Database.GetDbConnection(); const string query = @"DELETE FROM ERRORLIST; ALTER TABLE ERRORLIST AUTO_INCREMENT = 1"; conn.Execute(query); _context.ErrorList.AddRange(errorList); _context.SaveChanges(); return(Json(1)); } if (listItems != null && listItems.Any()) { var conn = _context.Database.GetDbConnection(); const string query = @"DELETE FROM TempData; ALTER TABLE TempData AUTO_INCREMENT = 1"; conn.Execute(query); _context.TempData.AddRange(listItems); _context.SaveChanges(); return(RedirectToAction("IsDescriptionMapped", "Mapping")); } return(BadRequest()); } catch (Exception e) { Console.WriteLine(e); throw; } }
private async Task <(Stream stream, IValueProvider formValueProvider)> GetFileStream(Stream body) { var formAccumulator = new KeyValueAccumulator(); var boundary = Helpers.MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(Request.ContentType), DefaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, HttpContext.Request.Body); MemoryStream fileStream = null; var section = await reader.ReadNextSectionAsync(); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { if (Helpers.MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { fileStream = new MemoryStream(); await section.Body.CopyToAsync(fileStream); } else if (Helpers.MultipartRequestHelper.HasFormDataContentDisposition(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 = 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.ToString(), value); if (formAccumulator.ValueCount > DefaultFormOptions.ValueCountLimit) { throw new InvalidDataException($"Form key count limit {DefaultFormOptions.ValueCountLimit} exceeded."); } } } } section = await reader.ReadNextSectionAsync(); } ; fileStream.ResetPosition(); var formValueProvider = new FormValueProvider( BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture); return(fileStream, formValueProvider); }
[RequestFormLimits(MultipartBodyLengthLimit = 4_294_967_294)] // 4GB public async Task <IActionResult> Post([FromServices] IMediator mediator) { if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { return(BadRequest($"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(); IData data = null; var boundary = MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(Request.ContentType), int.MaxValue); var reader = new MultipartReader(boundary, HttpContext.Request.Body); var section = await reader.ReadNextSectionAsync().ConfigureAwait(false); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { data = await _storage.CreateAsync(_storage.CreateKey(), section.Body); } else if (MultipartRequestHelper.HasFormDataContentDisposition(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 = 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); 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().ConfigureAwait(false); } // Bind form data to a model var formValueProvider = new FormValueProvider( BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture); var request = new UploadRequest { File = data }; var bindingSuccessful = await TryUpdateModelAsync(request, prefix : "", valueProvider : formValueProvider).ConfigureAwait(false); if (!bindingSuccessful) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } } return(await PostInternal(request, mediator).ConfigureAwait(false)); }
public async Task <IActionResult> UploadDatabase() { if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { ModelState.AddModelError("File", $"The request couldn't be processed (Error 1)."); // Log error return(BadRequest(ModelState)); } // Accumulate the form data key-value pairs in the request (formAccumulator). var formAccumulator = new KeyValueAccumulator(); var trustedFileNameForDisplay = string.Empty; var untrustedFileNameForStorage = string.Empty; var streamedFileContent = new byte[0]; var boundary = MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, HttpContext.Request.Body); var section = await reader.ReadNextSectionAsync(); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse( section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper .HasFileContentDisposition(contentDisposition)) { untrustedFileNameForStorage = contentDisposition.FileName.Value; // Don't trust the file name sent by the client. To display // the file name, HTML-encode the value. trustedFileNameForDisplay = WebUtility.HtmlEncode( contentDisposition.FileName.Value); streamedFileContent = await FileHelpers.ProcessStreamedFile(section, contentDisposition, ModelState, _permittedExtentions, _fileSizeLimit); if (!ModelState.IsValid) { return(BadRequest(ModelState)); } } else if (MultipartRequestHelper .HasFormDataContentDisposition(contentDisposition)) { // Don't limit the key name length because the // multipart headers length limit is already in effect. var key = HeaderUtilities .RemoveQuotes(contentDisposition.Name).Value; var encoding = GetEncoding(section); if (encoding == null) { ModelState.AddModelError("File", $"The request couldn't be processed (Error 2)."); // Log error return(BadRequest(ModelState)); } 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); if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit) { // Form key count limit of // _defaultFormOptions.ValueCountLimit // is exceeded. ModelState.AddModelError("File", $"The request couldn't be processed (Error 3)."); // Log error return(BadRequest(ModelState)); } } } } // Drain any remaining section body that hasn't been consumed and // read the headers for the next section. 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("File", "The request couldn't be processed (Error 5)."); // Log error return(BadRequest(ModelState)); } // **WARNING!** // In the following example, the file is saved without // scanning the file's contents. In most production // scenarios, an anti-virus/anti-malware scanner API // is used on the file before making the file available // for download or for use by other systems. // For more information, see the topic that accompanies // this sample app. var file = new ClamSectionAcademicSubCategoryItem() { ItemPath = null, ItemTitle = untrustedFileNameForStorage, ItemDescription = formData.Note, Size = streamedFileContent.Length, DateAdded = DateTime.Now, SubCategoryId = new Guid("8d7af8fa-4659-4aef-1746-08d7d7789232") }; _context.Add(file); await _context.SaveChangesAsync(); return(RedirectToAction(nameof(Index))); }
protected async Task <UploadModel> Upload(bool inMemory) { var formAccumulator = new KeyValueAccumulator(); var result = new UploadModel(); var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), formOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, HttpContext.Request.Body); var section = (MultipartSection)null; while ((section = await reader.ReadNextSectionAsync()) != null) { if (ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition)) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { result.FileName = contentDisposition.FileName.ToString(); if (inMemory) { result.Stream = new MemoryStream(); } else { result.FilePath = Path.GetTempFileName(); result.Stream = System.IO.File.Create(result.FilePath); } await section.Body.CopyToAsync(result.Stream); await result.Stream.FlushAsync(); } else if (MultipartRequestHelper.HasFormDataContentDisposition(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 = HeaderUtilities.RemoveQuotes(contentDisposition.Name); var encoding = GetEncoding(section); using (var streamReader = new StreamReader( section.Body, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: 2048, 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.ToString(), value); if (formAccumulator.ValueCount > formOptions.ValueCountLimit) { throw new InvalidDataException($"Form key count limit {formOptions.ValueCountLimit} exceeded."); } } } } } return(result); }
public static async Task <FormValueProvider> StreamFile(this HttpRequest request, Stream targetStream) { if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType)) { throw new Exception($"Expected a multipart request, but got {request.ContentType}"); } 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) { ContentDispositionHeaderValue contentDisposition; var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { await section.Body.CopyToAsync(targetStream); } else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition)) { var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name); var encoding = GetEncoding(section); 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.ToString(), value); if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit) { throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded."); } } } } section = await reader.ReadNextSectionAsync(); } var formValueProvider = new FormValueProvider( BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture); return(formValueProvider); }
public static async Task <FormValueProvider> StreamFile(this HttpRequest request, Stream targetStream) { 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 = null; 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) { ContentDispositionHeaderValue contentDisposition; var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { await section.Body.CopyToAsync(targetStream); } else if (MultipartRequestHelper.HasFormDataContentDisposition(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 = 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 <IActionResult> UploadDatabase() { if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { ModelState.AddModelError("File", $"The request couldn't be processed (Error 1)."); // Log error return(BadRequest(ModelState)); } // User Profile var name = User.Identity.Name; var profile = await _userManager.FindByNameAsync(name); // Accumulate the form data key-value pairs in the request (formAccumulator). var formAccumulator = new KeyValueAccumulator(); var trustedFileNameForDisplay = string.Empty; var untrustedFileNameForStorage = string.Empty; var trustedFilePathStorage = string.Empty; var trustedFileNameForFileStorage = string.Empty; var streamedFileImageContent = new byte[0]; var streamedFilePhysicalContent = new byte[0]; // List Byte for file storage List <byte[]> filesByteStorage = new List <byte[]>(); List <string> filesNameStorage = new List <string>(); List <string> storedPaths = new List <string>(); List <string> storedPathDictionaryKeys = new List <string>(); var fileStoredData = new Dictionary <string, byte[]>(); var boundary = MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, HttpContext.Request.Body); var section = await reader.ReadNextSectionAsync(); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse( section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper .HasFileContentDisposition(contentDisposition)) { untrustedFileNameForStorage = contentDisposition.FileName.Value; // Don't trust the file name sent by the client. To display // the file name, HTML-encode the value. trustedFileNameForDisplay = WebUtility.HtmlEncode( contentDisposition.FileName.Value); if (!Directory.Exists(_targetFilePath)) { string path = String.Format("{0}", _targetFilePath); Directory.CreateDirectory(path); } //streamedFileContent = // await FileHelpers.ProcessStreamedFile(section, contentDisposition, // ModelState, _permittedExtentions, _fileSizeLimit); streamedFilePhysicalContent = await FileHelpers.ProcessStreamedFile( section, contentDisposition, ModelState, _permittedExtentions, _fileSizeLimit); filesNameStorage.Add(trustedFileNameForDisplay); filesByteStorage.Add(streamedFilePhysicalContent); fileStoredData.Add(trustedFileNameForDisplay, streamedFilePhysicalContent); // Debug //var errors = ModelState.ErrorCount; //var errorView = ModelState.Where(x => x.Value.Errors.Count > 0) // .Select(x => new { x.Key, x.Value.Errors }).ToArray(); if (!ModelState.IsValid) { return(BadRequest(ModelState)); } } else if (MultipartRequestHelper .HasFormDataContentDisposition(contentDisposition)) { // Don't limit the key name length because the // multipart headers length limit is already in effect. var key = HeaderUtilities .RemoveQuotes(contentDisposition.Name).Value; var encoding = GetEncoding(section); if (encoding == null) { ModelState.AddModelError("File", $"The request couldn't be processed (Error 2)."); // Log error return(BadRequest(ModelState)); } 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); if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit) { // Form key count limit of // _defaultFormOptions.ValueCountLimit // is exceeded. ModelState.AddModelError("File", $"The request couldn't be processed (Error 3)."); // Log error return(BadRequest(ModelState)); } } } } // Drain any remaining section body that hasn't been consumed and // read the headers for the next section. section = await reader.ReadNextSectionAsync(); } // Bind form data to the model var formData = new StreamFormDataBooks(); var formValueProvider = new FormValueProvider( BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture); var bindingSuccessful = await TryUpdateModelAsync(formData, prefix : "", valueProvider : formValueProvider); var keyPathFolder = FilePathUrlHelper.GenerateKeyPath(profile.Id); trustedFilePathStorage = String.Format("{0}\\{1}\\{2}\\{3}", _targetFolderPath, keyPathFolder, GenerateSecurity.Encode(profile.Id), Path.GetRandomFileName()); if (!bindingSuccessful) { ModelState.AddModelError("File", "The request couldn't be processed (Error 5)."); // Log error return(BadRequest(ModelState)); } // **WARNING!** // In the following example, the file is saved without // scanning the file's contents. In most production // scenarios, an anti-virus/anti-malware scanner API // is used on the file before making the file available // for download or for use by other systems. // For more information, see the topic that accompanies // this sample app. Directory.CreateDirectory(trustedFilePathStorage); foreach (var item in fileStoredData) { using (var targetStream = System.IO.File.Create( Path.Combine(trustedFilePathStorage, item.Key))) { await targetStream.WriteAsync(item.Value); _logger.LogInformation( "Uploaded file '{TrustedFileNameForDisplay}' saved to " + "'{TargetFilePath}' as {TrustedFileNameForFileStorage}", item.Key, trustedFilePathStorage, item.Key); } storedPaths.Add(Path.Combine(trustedFilePathStorage, item.Key)); storedPathDictionaryKeys.Add(item.Key); } var keyValue = storedPathDictionaryKeys[0]; var keyConvert = fileStoredData[keyValue]; var file = new ClamUserBooks() { BookTitle = formData.BookTitle, ItemPath = storedPaths[0], ImagePath = storedPaths[1], Size = keyConvert.Length, DateCreated = DateTime.Now, Status = bool.Parse(formData.Status), UserId = profile.Id }; _context.Add(file); await _context.SaveChangesAsync(); return(RedirectToAction(nameof(Index))); }