public async Task PostImportAsync() { using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context)) { if (HttpContext.Request.HasFormContentType == false) { HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; // Bad request using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream())) { context.Write(writer, new DynamicJsonValue { ["Type"] = "Error", ["Error"] = "This endpoint requires form content type" }); return; } } var operationId = GetLongQueryString("operationId", false) ?? Database.Operations.GetNextOperationId(); var token = CreateOperationToken(); var result = new SmugglerResult(); await Database.Operations.AddOperation(Database, "Import to: " + Database.Name, Operations.OperationType.DatabaseImport, onProgress => { return(Task.Run(async() => { try { var boundary = MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(HttpContext.Request.ContentType), MultipartRequestHelper.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, HttpContext.Request.Body); DatabaseSmugglerOptionsServerSide options = null; while (true) { var section = await reader.ReadNextSectionAsync().ConfigureAwait(false); if (section == null) { break; } if (ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out ContentDispositionHeaderValue contentDisposition) == false) { continue; } if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition)) { var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name); if (key != "importOptions") { continue; } BlittableJsonReaderObject blittableJson; if (section.Headers.ContainsKey("Content-Encoding") && section.Headers["Content-Encoding"] == "gzip") { using (var gzipStream = new GZipStream(section.Body, CompressionMode.Decompress)) { blittableJson = await context.ReadForMemoryAsync(gzipStream, "importOptions"); } } else { blittableJson = await context.ReadForMemoryAsync(section.Body, "importOptions"); } options = JsonDeserializationServer.DatabaseSmugglerOptions(blittableJson); continue; } if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition) == false) { continue; } var stream = new GZipStream(section.Body, CompressionMode.Decompress); DoImportInternal(context, stream, options, result, onProgress, token); } } catch (Exception e) { result.AddError($"Error occurred during import. Exception: {e.Message}"); onProgress.Invoke(result.Progress); throw; } return (IOperationResult)result; })); }, operationId, token).ConfigureAwait(false); WriteImportResult(context, result, ResponseBodyStream()); }
public async Task <IFormCollection> ReadFormAsync(CancellationToken cancellationToken) { if (Form != null) { return(Form); } if (!HasFormContentType) { throw new InvalidOperationException("Incorrect Content-Type: " + _request.ContentType); } cancellationToken.ThrowIfCancellationRequested(); _request.EnableRewind(); IDictionary <string, StringValues> formFields = null; var files = new FormFileCollection(); // Some of these code paths use StreamReader which does not support cancellation tokens. using (cancellationToken.Register(_request.HttpContext.Abort)) { var contentType = ContentType; // Check the content-type if (HasApplicationFormContentType(contentType)) { var encoding = FilterEncoding(contentType.Encoding); formFields = await FormReader.ReadFormAsync(_request.Body, encoding, cancellationToken); } else if (HasMultipartFormContentType(contentType)) { var formAccumulator = new KeyValueAccumulator(); var boundary = GetBoundary(contentType); var multipartReader = new MultipartReader(boundary, _request.Body); var section = await multipartReader.ReadNextSectionAsync(cancellationToken); while (section != null) { var headers = new HeaderDictionary(section.Headers); ContentDispositionHeaderValue contentDisposition; ContentDispositionHeaderValue.TryParse(headers[HeaderNames.ContentDisposition], out contentDisposition); if (HasFileContentDisposition(contentDisposition)) { // Find the end await section.Body.DrainAsync(cancellationToken); var file = new FormFile(_request.Body, section.BaseStreamOffset.Value, section.Body.Length) { Headers = headers, }; files.Add(file); } else if (HasFormDataContentDisposition(contentDisposition)) { // Content-Disposition: form-data; name="key" // // value var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name); MediaTypeHeaderValue mediaType; MediaTypeHeaderValue.TryParse(headers[HeaderNames.ContentType], out mediaType); var encoding = FilterEncoding(mediaType?.Encoding); using (var reader = new StreamReader(section.Body, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true)) { var value = await reader.ReadToEndAsync(); formAccumulator.Append(key, value); } } else { System.Diagnostics.Debug.Assert(false, "Unrecognized content-disposition for this section: " + headers[HeaderNames.ContentDisposition]); } section = await multipartReader.ReadNextSectionAsync(cancellationToken); } formFields = formAccumulator.GetResults(); } } // Rewind so later readers don't have to. _request.Body.Seek(0, SeekOrigin.Begin); Form = new FormCollection(formFields, files); return(Form); }
private ParserState ProcessRequest(HttpRequestMessageBuilder request, ParserState currentState, string content) { switch (currentState) { case ParserState.RequestLine: // From RFC2616: "In the interest of robustness, servers SHOULD ignore any empty line(s) received where a Request-Line is expected." if (content.Length == 0) { return(currentState); } var requestLine = content.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); // Verbs are case-sensitive switch (requestLine.Length > 0 ? requestLine[0] : null) { case "OPTIONS": request.Method = HttpMethod.Options; break; case "GET": request.Method = HttpMethod.Get; break; case "HEAD": request.Method = HttpMethod.Head; break; case "POST": request.Method = HttpMethod.Post; break; case "PUT": request.Method = HttpMethod.Put; break; case "DELETE": request.Method = HttpMethod.Delete; break; case "TRACE": request.Method = HttpMethod.Trace; break; default: break; } request.RequestUri = ResolveTargetUri(requestLine.Length > 1 ? requestLine[1] : "/"); var protocolVersion = Regex.Match(requestLine.Length > 2 ? requestLine[2] : null, "HTTP/(?<version>.*)").Groups["version"].Value; Version version; if (Version.TryParse(protocolVersion, out version)) { request.Version = version; } return(ParserState.RequestHeaders); case ParserState.RequestHeaders: // empty line signals end of request header if (content.Length > CrLf.Length) { // Header names are case-insensitive var header = content.Split(new[] { ':' }, 2, StringSplitOptions.RemoveEmptyEntries); var headerName = header.Length > 0 ? header[0].Trim() : null; var headerValue = header.Length > 1 ? header[1].Trim() : null; if (headerName != null && headerValue != null) { switch (headerName.ToUpperInvariant()) { case "RANGE": // fixes issue in HttpClient for WP where a Range header with no upper range // results in an InvalidOperationException - "Nullable object must have a value" if (headerValue.EndsWith("-")) { headerValue += long.MaxValue.ToString(); } request.Headers.Add(headerName, headerValue); break; case "REFERER": headerValue = ResolveTargetUri(headerValue).AbsoluteUri; request.Headers.Add(headerName, headerValue); break; case "HOST": break; case "CONNECTION": break; case "ALLOW": case "CONTENT-ENCODING": case "CONTENT-LANGUAGE": request.ContentHeaders[headerName] = headerValue; break; case "CONTENT-DISPOSITION": ContentDispositionHeaderValue contentDisposition; if (ContentDispositionHeaderValue.TryParse(headerValue, out contentDisposition)) { request.ContentHeaders[headerName] = contentDisposition; } break; case "CONTENT-LENGTH": long contentLength; if (long.TryParse(headerValue, out contentLength)) { request.ContentHeaders[headerName] = contentLength; } break; case "CONTENT-LOCATION": var contentLocation = ResolveTargetUri(headerValue).AbsoluteUri; request.ContentHeaders[headerName] = contentLocation; break; case "CONTENT-MD5": // currently not supported break; case "CONTENT-RANGE": ContentRangeHeaderValue contentRange; if (ContentRangeHeaderValue.TryParse(headerValue, out contentRange)) { request.ContentHeaders[headerName] = contentRange; } break; case "CONTENT-TYPE": MediaTypeHeaderValue contentType; if (MediaTypeHeaderValue.TryParse(headerValue, out contentType)) { request.ContentHeaders[headerName] = contentType; } break; case "CONTENT-EXPIRES": case "CONTENT-LASTMODIFIED": DateTimeOffset expires; if (DateTimeOffset.TryParse(headerValue, out expires)) { request.ContentHeaders[headerName] = expires; } break; case "USER-AGENT": request.Headers.TryAddWithoutValidation("User-Agent", headerValue.Replace(")", "; WAT)")); break; case "COOKIE": // filter out cookies for other domains var filteredCookies = this.cookieManager.FilterCookiesForCurrentRequest(request.RequestUri, headerValue); if (!string.IsNullOrWhiteSpace(filteredCookies)) { request.Headers.Add(headerName, filteredCookies); } break; default: request.Headers.Add(headerName, headerValue); break; } } } else { currentState = ParserState.RequestBody; } break; case ParserState.RequestBody: request.Content = new StringContent(content); currentState = ParserState.Complete; break; } return(currentState); }
public async Task PostImportAsync() { DocumentsOperationContext context; using (ContextPool.AllocateOperationContext(out context)) { if (HttpContext.Request.HasFormContentType == false) { HttpContext.Response.StatusCode = 400; // Bad request using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream())) { context.Write(writer, new DynamicJsonValue { ["Type"] = "Error", ["Error"] = "This endpoint requires form content type" }); return; } } var operationId = GetLongQueryString("operationId", required: true) ?? -1; var token = CreateOperationToken(); var sp = Stopwatch.StartNew(); var result = new ImportResult(); await Database.Operations.AddOperation("Import to: " + Database.Name, DatabaseOperations.PendingOperationType.DatabaseImport, onProgress => { return(Task.Run(async() => { try { var boundary = MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(HttpContext.Request.ContentType), MultipartRequestHelper.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, HttpContext.Request.Body); DatabaseSmugglerOptions smugglerOptions = null; while (true) { var section = await reader.ReadNextSectionAsync().ConfigureAwait(false); if (section == null) { break; } ContentDispositionHeaderValue contentDisposition; var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition); if (hasContentDispositionHeader == false) { continue; } if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition)) { var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name); if (key != "importOptions") { continue; } var blittableJson = await context.ReadForMemoryAsync(section.Body, "importOptions"); smugglerOptions = JsonDeserializationServer.DatabaseSmugglerOptions(blittableJson); continue; } if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition) == false) { continue; } var stream = new GZipStream(section.Body, CompressionMode.Decompress); var fileImport = await DoImportInternal(context, stream, smugglerOptions, onProgress).ConfigureAwait(false); result.DocumentsCount += fileImport.DocumentsCount; result.Warnings.AddRange(fileImport.Warnings); result.IdentitiesCount += fileImport.IdentitiesCount; result.Message = fileImport.Message; result.RevisionDocumentsCount += fileImport.RevisionDocumentsCount; result.IndexesCount += fileImport.IndexesCount; result.TransformersCount += fileImport.TransformersCount; } } catch (Exception e) { result.Message = $"Error occured during export. Exception: {e.Message}"; result.Exception = e.ToString(); } return (IOperationResult)result; })); }, operationId, token).ConfigureAwait(false); WriteImportResult(context, sp, result, ResponseBodyStream()); } }
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; 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}'", 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); 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 <MediaModel> TryLoadMediaModelAsync() { var model = new MediaModel(); try { var formAccumulator = new KeyValueAccumulator(); var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), DefaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary.Value, HttpContext.Request.Body); var section = await reader.ReadNextSectionAsync(); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out ContentDispositionHeaderValue contentDisposition); if (hasContentDispositionHeader) { if (contentDisposition == null || !contentDisposition.DispositionType.Equals("form-data")) { continue; } if (contentDisposition.FileName.HasValue || contentDisposition.FileNameStar.HasValue) { if (!SupportedMimeTypes.Contains(section.ContentType)) { throw new NotSupportedException($"{section.ContentType}"); } var targetFilePath = Path.GetTempFileName(); using (var targetStream = System.IO.File.Create(targetFilePath)) { await section.Body.CopyToAsync(targetStream); _logger.LogInformation($"Copied the uploaded file '{targetFilePath}'"); } model.FilePath = targetFilePath; model.FileName = contentDisposition.FileName.Value; } else { var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name); var encoding = GetEncoding(section); using (var streamReader = new StreamReader(section.Body, encoding, true, 1024, true)) { var value = await streamReader.ReadToEndAsync(); if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase)) { value = string.Empty; } formAccumulator.Append(key.Value, value.ToLower()); 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); var bindingSuccessful = await TryUpdateModelAsync(model, string.Empty, formValueProvider); if (bindingSuccessful) { return(model); } } catch (Exception e) { _logger.LogError(e, e.Message); if (!string.IsNullOrEmpty(model.FileName) && System.IO.File.Exists(model.FileName)) { System.IO.File.Delete(model.FileName); } ModelState.AddModelError(string.Empty, e.Message); } return(null); }
public async Task <ActionResult> Post(bool thumbinal = false, bool forContent = false) { logger.LogDebug("Start FileController Post"); // Check if the request contains multipart/form-data. if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { logger.LogError($"The request couldn't be processed (Error 1)."); return(BadRequest($"The request couldn't be processed (Error 1).")); } try { var boundary = MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, HttpContext.Request.Body); List <ObjectFileField> files = new List <ObjectFileField>(); var section = await reader.ReadNextSectionAsync(); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse( section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper .HasFileContentDisposition(contentDisposition)) { // Don't trust the file name sent by the client. To display // the file name, HTML-encode the value. var trustedFileNameForDisplay = WebUtility.HtmlEncode( contentDisposition.FileName.Value); logger.LogInformation("the raw file name is : " + trustedFileNameForDisplay); var extension = Path.GetExtension(contentDisposition.FileName.Value); long fileSizeLimit = long.Parse(mConfiguration["SiteSettings:FileUpload:FileSizeLimit"]); FileStorageInfo info = await storageService.SaveFileAsync(section.Body, extension, thumbinal, trustedFileNameForDisplay); logger.LogDebug("file save path : " + info.FileUri); //FileHelper.ProcessStreamedFile(section, contentDisposition, // _permittedExtensions, fileSizeLimit); files.Add(new ObjectFileField() { FileName = trustedFileNameForDisplay, //FileFullPath = info.FileUri, FileUrl = string.Format("/api/Files/DownloadFile/{0}/{1}", info.FileUniqueName, WebUtility.UrlEncode(trustedFileNameForDisplay)), FileExtension = extension, Updated = info.LastUpdated, Created = info.Creation, FileCRC = info.CRC, FileSize = (int)(info.Size / 1024), }); //only care about single document. if (forContent) { break; } } // Drain any remaining section body that hasn't been consumed and // read the headers for the next section. section = await reader.ReadNextSectionAsync(); } } //return the action result. ActionResult result = forContent ? this.Ok(new UploadFile() { uploaded = 1, fileName = files[0].FileName, url = files[0].FileUrl }) : this.Ok(new { status = "success", files = files }); logger.LogDebug("End FileController Post"); return(result); } catch (Exception ex) { logger.LogError(ex.Message); return(BadRequest(ex.GetBaseException().Message)); } }
public async Task <MultiPartRequestDto> HandleMultiPartRequest(HttpRequest request) { if (!IsMultipartContentType(request.ContentType)) { throw new Exception($"Expected a multipart request, but got {request.ContentType}"); } var formAccumulator = new KeyValueAccumulator(); var boundary = GetBoundary( MediaTypeHeaderValue.Parse(request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, request.Body); var section = await reader.ReadNextSectionAsync(); var media = new List <AddFileDto>(); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { if (HasFileContentDisposition(contentDisposition)) { var processedMedia = await _fileService.ProcessStreamedFileAsync(section, contentDisposition); var mediaDto = new AddFileDto { File = processedMedia, FileExtension = Path.GetExtension(contentDisposition.FileName.Value), }; media.Add(mediaDto); } else if (HasFormDataContentDisposition(contentDisposition)) { 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)) { var value = await streamReader.ReadToEndAsync(); if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase)) { value = string.Empty; } formAccumulator.Append(key, value); if (formAccumulator.ValueCount > int.MaxValue) { throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded."); } } } } section = await reader.ReadNextSectionAsync(); } //request.Body.Position = 0; var formAccumulatorResults = formAccumulator.GetResults(); var formValueProvider = new FormValueProvider( BindingSource.Form, new FormCollection(formAccumulatorResults), CultureInfo.CurrentCulture); return(new MultiPartRequestDto { FormValueProvider = formValueProvider, File = media, }); }
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)); }
/// <summary> /// Creates a data element by reading the first multipart element or body of the request. /// </summary> private async Task <(Stream, DataElement)> ReadRequestAndCreateDataElementAsync(HttpRequest request, string elementType, List <Guid> refs, Instance instance) { DateTime creationTime = DateTime.UtcNow; Stream theStream = null; string contentType = null; string contentFileName = null; long fileSize = 0; if (MultipartRequestHelper.IsMultipartContentType(request.ContentType)) { // Only read the first section of the mulitpart message. MediaTypeHeaderValue mediaType = MediaTypeHeaderValue.Parse(request.ContentType); string boundary = MultipartRequestHelper.GetBoundary(mediaType, _defaultFormOptions.MultipartBoundaryLengthLimit); MultipartSection section = null; MultipartReader reader = new MultipartReader(boundary, request.Body); section = await reader.ReadNextSectionAsync(); theStream = section.Body; contentType = section.ContentType; bool hasContentDisposition = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out ContentDispositionHeaderValue contentDisposition); if (hasContentDisposition) { contentFileName = HttpUtility.UrlDecode(contentDisposition.FileName.ToString()); fileSize = contentDisposition.Size ?? 0; } } else { theStream = request.Body; if (request.Headers.TryGetValue("Content-Disposition", out StringValues headerValues)) { string contentDisposition = headerValues.ToString(); List <string> contenDispValues = contentDisposition.Split(';').ToList(); string fileNameValue = contenDispValues.FirstOrDefault(x => x.Contains("filename", StringComparison.CurrentCultureIgnoreCase)); if (!string.IsNullOrEmpty(fileNameValue)) { string[] valueParts = fileNameValue.Split('='); if (valueParts.Count() == 2) { contentFileName = HttpUtility.UrlDecode(valueParts[1]); } } } contentType = request.ContentType; } string user = null; DataElement newData = DataElementHelper.CreateDataElement(elementType, refs, instance, creationTime, contentType, contentFileName, fileSize, user); return(theStream, newData); }
public async Task <IActionResult> Post() { 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; 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); Console.WriteLine($"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.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(); } IDictionary <string, StringValues> parameters = formAccumulator.GetResults(); if (parameters.ContainsKey(PARAM_ID_CONCEPT_LIE)) { Debugger.Log((int)LogLevel.Information, "Info", parameters[PARAM_ID_CONCEPT_LIE].ToString()); } else { Debugger.Log((int)LogLevel.Error, "Info", $"La requête ne contenait pas le paramètre {PARAM_ID_CONCEPT_LIE}"); } return(Ok(new { FilePath = targetFilePath })); }
public async Task <ActionResult <BlobInfo[]> > UploadAssetAsync([FromQuery] string folderUrl, [FromQuery] string url = null, [FromQuery] string name = null) { // https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-3.1 if (url == null && !MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { return(BadRequest($"Expected a multipart request, but got {Request.ContentType}")); } var retVal = new List <BlobInfo>(); if (url != null) { var fileName = name ?? HttpUtility.UrlDecode(Path.GetFileName(url)); var fileUrl = folderUrl + "/" + fileName; using (var client = new WebClient()) using (var blobStream = _blobProvider.OpenWrite(fileUrl)) using (var remoteStream = client.OpenRead(url)) { remoteStream.CopyTo(blobStream); var blobInfo = AbstractTypeFactory <BlobInfo> .TryCreateInstance(); blobInfo.Name = fileName; blobInfo.RelativeUrl = fileUrl; blobInfo.Url = _urlResolver.GetAbsoluteUrl(fileUrl); retVal.Add(blobInfo); } } else { var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, HttpContext.Request.Body); var section = await reader.ReadNextSectionAsync(); if (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { var fileName = contentDisposition.FileName.Value; var targetFilePath = folderUrl + "/" + fileName; using (var targetStream = _blobProvider.OpenWrite(targetFilePath)) { await section.Body.CopyToAsync(targetStream); } var blobInfo = AbstractTypeFactory <BlobInfo> .TryCreateInstance(); blobInfo.Name = fileName; blobInfo.RelativeUrl = targetFilePath; blobInfo.Url = _urlResolver.GetAbsoluteUrl(targetFilePath); blobInfo.ContentType = MimeTypeResolver.ResolveContentType(fileName); retVal.Add(blobInfo); } } } } return(Ok(retVal.ToArray())); }
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 trustedFilePathStorage = string.Empty; var trustedFileNameForFileStorage = string.Empty; var streamedFileContent = 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>(); var fileStoredData = new Dictionary <string, byte[]>(); List <string> storedPaths = new List <string>(); List <string> storedPathDictionaryKeys = new List <string>(); // List to Submit List <ClamSectionTVShowSubCategorySeasonItem> episodeList = new List <ClamSectionTVShowSubCategorySeasonItem>(); 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); streamedFilePhysicalContent = await FileHelpers.ProcessStreamedFile( section, contentDisposition, ModelState, _permittedExtentions, _fileSizeLimit); filesNameStorage.Add(trustedFileNameForDisplay); filesByteStorage.Add(streamedFilePhysicalContent); fileStoredData.Add(trustedFileNameForDisplay, streamedFilePhysicalContent); 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 StreamFormData(); var formValueProvider = new FormValueProvider( BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture); var bindingSuccessful = await TryUpdateModelAsync(formData, prefix : "", valueProvider : formValueProvider); //trustedFilePathStorage = String.Format("{0}\\{1}\\{2}\\{3}\\{4}", // //_targetFilePath, // _targetFolderPath, // formData.CategoryId, // formData.TVShowId, // formData.SeasonId, // 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); //using (var targetStream = System.IO.File.Create( // Path.Combine(trustedFilePathStorage, trustedFileNameForDisplay))) //{ // await targetStream.WriteAsync(streamedFilePhysicalContent); // _logger.LogInformation( // "Uploaded file '{TrustedFileNameForDisplay}' saved to " + // "'{TargetFilePath}' as {TrustedFileNameForFileStorage}", // trustedFileNameForDisplay, trustedFilePathStorage, // trustedFileNameForDisplay); //} foreach (var item in fileStoredData) { trustedFilePathStorage = String.Format("{0}\\{1}\\{2}\\{3}\\{4}", //_targetFilePath, _targetFolderPath, formData.CategoryId, formData.TVShowId, formData.SeasonId, Path.GetRandomFileName()); Directory.CreateDirectory(trustedFilePathStorage); 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); episodeList.Add(new ClamSectionTVShowSubCategorySeasonItem() { ItemPath = Path.Combine(trustedFilePathStorage, item.Key), ItemTitle = item.Key, Size = item.Value.Length, DateCreated = DateTime.Now, CategoryId = formData.CategoryId, TVShowId = formData.TVShowId, SeasonId = formData.SeasonId }); } //var file = new ClamSectionTVShowSubCategorySeasonItem() //{ // ItemPath = Path.Combine(trustedFilePathStorage, trustedFileNameForDisplay), // ItemTitle = untrustedFileNameForStorage, // Size = streamedFilePhysicalContent.Length, // DateCreated = DateTime.Now, // CategoryId = formData.CategoryId, // TVShowId = formData.TVShowId, // SeasonId = formData.SeasonId //}; //_context.Add(file); await _context.AddRangeAsync(episodeList); await _context.SaveChangesAsync(); var url = String.Format("{0}/{1}/season/{2}/episodes/{3}", formData.UrlCategory, formData.UrlSection, formData.UrlSubSection, formData.CategoryId ); return(RedirectToAction("Episode", "TVShow", new { id = formData.CategoryId, show = formData.TVShowId, season = formData.SeasonId, category = formData.UrlCategory, section = formData.UrlSection, subsection = formData.UrlSubSection })); }
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 <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) { ContentDispositionHeaderValue contentDisposition; ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition); if (HasFileContentDisposition(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 = HeaderUtilities.RemoveQuotes(contentDisposition.Name) ?? string.Empty; var fileName = HeaderUtilities.RemoveQuotes(contentDisposition.FileName) ?? string.Empty; 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 (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 reader = new StreamReader(section.Body, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true)) { // The value length limit is enforced by MultipartBodyLengthLimit var value = await reader.ReadToEndAsync(); 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 async Task Process( HttpRequest request, Func <NameValueCollection, Stream> getDestinationStream, Action <FileUploadStatus> statusUpdate, Action <FormOptions> optionsAction, Action <NameValueCollection> postProcess = null ) { if (!request.ContentType.IsMultipartContentType()) { throw new InvalidOperationException($"Expected a multipart request, but got {request.ContentType}"); } if (optionsAction != null) { optionsAction.Invoke(_formOptions); } string boundary = request.ContentType.GetBoundary(); NameValueCollection metadata = new NameValueCollection(); MultipartReader reader = new MultipartReader(boundary, request.Body); MultipartSection section = await reader.ReadNextSectionAsync(); while (section != null) { bool hasContentDispositionHeader = ContentDispositionHeaderValue .TryParse(section.ContentDisposition, out ContentDispositionHeaderValue contentDisposition); if (hasContentDispositionHeader) { if (contentDisposition.HasFormDataContentDisposition()) { //add form values to metadata collection 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 string value = await streamReader.ReadToEndAsync(); if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase)) { value = String.Empty; } metadata = value.ParseFormValues(); } } if (contentDisposition.HasFileContentDisposition()) { metadata.Add("original-name", HeaderUtilities.RemoveQuotes(contentDisposition.FileName).Value); try { Stream targetStream = getDestinationStream.Invoke(metadata); FileUploadStatus status = new FileUploadStatus { Metadata = metadata, Key = metadata["monitor-key"] ?? $"{metadata["group-key"]}-{metadata["original-name"]}", Size = Int64.Parse(metadata["size"] ?? "1E9") }; await Save(section.Body, targetStream, status, statusUpdate); if (postProcess != null) { postProcess.Invoke(metadata); } } catch (Exception ex) { throw ex; } } } // Drains any remaining section body that has not been consumed and // reads the headers for the next section. section = await reader.ReadNextSectionAsync(); } }
public async Task <IActionResult> SaveFileToPhysicalFolder() { var boundary = HeaderUtilities.RemoveQuotes( MediaTypeHeaderValue.Parse(Request.ContentType).Boundary ).Value; var reader = new MultipartReader(boundary, Request.Body); var section = await reader.ReadNextSectionAsync(); var formAccumelator = new KeyValueAccumulator(); while (section != null) { var hasContentDisposition = ContentDispositionHeaderValue.TryParse( section.ContentDisposition, out var contentDisposition ); if (hasContentDisposition) { if (contentDisposition.DispositionType.Equals("form-data") && (!string.IsNullOrEmpty(contentDisposition.FileName.Value) || !string.IsNullOrEmpty(contentDisposition.FileNameStar.Value))) { string fileStoragePath = $"{_webHostEnvironment.WebRootPath}/images/"; string fileName = Path.GetRandomFileName() + ".jpg"; // uploaded files form fileds byte[] fileByteArray; using (var memoryStream = new MemoryStream()) { await section.Body.CopyToAsync(memoryStream); fileByteArray = memoryStream.ToArray(); } using (var fileStream = System.IO.File.Create(Path.Combine(fileStoragePath, fileName))) { await fileStream.WriteAsync(fileByteArray); } } else { var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name).Value; using (var streamReader = new StreamReader(section.Body, encoding: Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true)){ var value = await streamReader.ReadToEndAsync(); if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase)) { value = string.Empty; } formAccumelator.Append(key, value); } } } section = await reader.ReadNextSectionAsync(); } var profile = new Profile(); var formValueProvidere = new FormValueProvider( BindingSource.Form, new FormCollection(formAccumelator.GetResults()), CultureInfo.CurrentCulture ); var bindindSuccessfully = await TryUpdateModelAsync(profile, "", formValueProvidere); if (ModelState.IsValid) { // write log to save profile data to database } return(Content("Uploaded successfully")); }
/// Streamed Upload public async static Task <int> Upload(HttpRequest request, IFile filesys, string targetFolder, string filename, long fileSizeLimit, string[] permittedExtensions) { long _fileSizeLimit = fileSizeLimit; int reason = 0; if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType)) { throw new Exception("Failed on Request.ContentType = " + request.ContentType + " (Error 1)"); } MediaTypeHeaderValue contentType = MediaTypeHeaderValue.Parse(request.ContentType); // Use the default form options to set the default limits for request body data. int lengthLimit = (new FormOptions()).MultipartBoundaryLengthLimit; string boundary = MultipartRequestHelper.GetBoundary(contentType, lengthLimit); MultipartReader reader = new MultipartReader(boundary, request.Body); MultipartSection section = await reader.ReadNextSectionAsync(); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse( section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { // This check assumes that there's a file present without form data. // If form data is present, this method immediately fails and returns the error. if (!MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { throw new Exception("Failed on Content Disposition (Error 2)"); } else { // In the following, 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. using (var stream = new MemoryStream()) { await section.Body.CopyToAsync(stream); string sourceFilename = contentDisposition.FileName.Value; reason = FileHelpers.CheckStreamSize(stream, _fileSizeLimit); if (reason == 0) { reason = FileHelpers.CheckStreamContent(stream, sourceFilename, permittedExtensions); } if (reason == 0) { byte[] bytes = stream.ToArray(); Stream stream2 = new MemoryStream(bytes); filesys.ChangeDirectory(targetFolder); string ext = Path.GetExtension(sourceFilename).ToLowerInvariant(); if (filename == null) { filename = WebUtility.HtmlEncode(sourceFilename); } filename = Path.ChangeExtension(filename, ext); filesys.FileUpload(filename, stream2); Log.Me.Info("Uploaded " + WebUtility.HtmlEncode(sourceFilename) + " as " + filename); } } } } // Drain any remaining section body that hasn't been consumed and // read the headers for the next section. section = await reader.ReadNextSectionAsync(); } return(reason); }
public static async Task <FormValueProvider> StreamFile(this HttpRequest request, Func <FileMultipartSection, Stream> createStream) { if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType)) { throw new Exception($"Expected a multipart request, but got {request.ContentType}"); } // 把 request 中的 Form 依照 Key 及 Value 存到此物件 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) { // 把 Form 的欄位內容逐一取出 ContentDispositionHeaderValue contentDisposition; var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { // 若此欄位是檔案,就寫入至 Stream; using (var targetStream = createStream(section.AsFileSection())) { await section.Body.CopyToAsync(targetStream); } } else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition)) { // 若此欄位不是檔案,就把 Key 及 Value 取出,存入 formAccumulator 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)) { 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."); } } } } // 取得 Form 的下一個欄位 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)); } // 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) { untrustedFileNameForStorage = contentDisposition.FileName.Value; trustedFileNameForDisplay = WebUtility.HtmlEncode(contentDisposition.FileName.Value); streamedFileContent = await FileHelpers.ProcessStreamedFile(section, contentDisposition, ModelState, _permittedExtensions, _fileSizeLimit); if (!ModelState.IsValid) { return(BadRequest(ModelState)); } } else if (MultipartRequestHelper .HasFormDataContentDisposition(contentDisposition)) { // 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); 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. var file = new AppFile { Content = streamedFileContent, UntrustedName = untrustedFileNameForStorage, Note = formData.Note, UploadDT = DateTime.UtcNow }; _appDbContext.AppFiles.Add(file); await _appDbContext.SaveChangesAsync(); return(Created(nameof(StreamingController), null)); }
/// 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 <(GroupDto, ImageDto?)> UploadGroupImageMultipartContent(GroupData groupData, Guid userId, string slug, Stream requestBody, byte[] rowVersion, 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 now = _systemClock.UtcNow.UtcDateTime; 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); ImageDto?imageDto = null; GroupDto groupDto = new GroupDto(); // 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}"; if (!_acceptedFileTypes.Contains(fileExtension.ToLower())) { _logger.LogError("file extension:{0} is not an accepted image file", fileExtension); throw new ValidationException("Image", "The image is not in an accepted format"); } var compressedImage = _imageService.TransformImageForGroupHeader(section.Body); try { await _blobStorageProvider.UploadFileAsync(compressedImage.Image, uniqueFileName, MimeTypesMap.GetMimeType(encodedFileName), cancellationToken); } catch (Exception ex) { _logger.LogError(ex, "An error occurred uploading file to blob storage"); throw; } // trick to get the size without reading the stream in memory var size = section.Body.Position; // 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"); //} imageDto = new ImageDto { FileSizeBytes = size, FileName = uniqueFileName, Height = compressedImage.Height, Width = compressedImage.Width, IsDeleted = false, MediaType = compressedImage.MediaType, CreatedBy = userId, CreatedAtUtc = now }; var imageValidator = new ImageValidator(MaxFileSizeBytes); var imageValidationResult = await imageValidator.ValidateAsync(imageDto, cancellationToken); if (imageValidationResult.Errors.Count > 0) { await _blobStorageProvider.DeleteFileAsync(uniqueFileName); _logger.LogError("File size:{0} is greater than the max allowed size:{1}", size, MaxFileSizeBytes); throw new ValidationException(imageValidationResult); } } } 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("GroupEdit: 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(); // Get values from multipart form var nameFound = formValues.TryGetValue("name", out var name); if (nameFound is false) { throw new ValidationException("Name", "Name was not provided"); } var straplineFound = formValues.TryGetValue("strapline", out var strapline); if (straplineFound is false) { throw new ValidationException("Strapline", "Strapline was not provided"); } formValues.TryGetValue("themeid", out var theme); if (Guid.TryParse(theme, out var themeId) is false || themeId == new Guid()) { throw new ValidationException(nameof(GroupDto.ThemeId), "Theme was not provided"); } formValues.TryGetValue("imageid", out var image); var imageId = Guid.TryParse(image, out var imageGuid) ? (Guid?)imageGuid : null; if (imageId.HasValue) { if (imageId == new Guid()) { throw new ArgumentOutOfRangeException($"Incorrect Id provided"); } } formValues.TryGetValue("isPublic", out var publicGroup); var isPublic = bool.TryParse(publicGroup, out var isPublicBool) ? isPublicBool : false; if (!groupData.IsPublic) { if (isPublic != groupData.IsPublic) { throw new ValidationException("isPublic", "Cannot make a private group public"); } } groupDto = new GroupDto { Slug = slug, Name = _htmlSanitizer.Sanitize(name), Strapline = _htmlSanitizer.Sanitize(strapline), ThemeId = themeId, ImageId = imageId, ModifiedBy = userId, ModifiedAtUtc = now, IsPublic = isPublic, RowVersion = rowVersion }; } return(groupDto, imageDto); }
public async Task <ActionResult <ModuleDescriptor> > UploadModuleArchive() { EnsureModulesCatalogInitialized(); ModuleDescriptor result = null; if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { return(BadRequest($"Expected a multipart request, but got {Request.ContentType}")); } var uploadPath = Path.GetFullPath(_platformOptions.LocalUploadFolderPath); if (!Directory.Exists(uploadPath)) { Directory.CreateDirectory(uploadPath); } 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(); if (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { var fileName = contentDisposition.FileName.Value; targetFilePath = Path.Combine(uploadPath, fileName); using (var targetStream = System.IO.File.Create(targetFilePath)) { await section.Body.CopyToAsync(targetStream); } } } using (var packageStream = System.IO.File.Open(targetFilePath, FileMode.Open)) using (var package = new ZipArchive(packageStream, ZipArchiveMode.Read)) { var entry = package.GetEntry("module.manifest"); if (entry != null) { using (var manifestStream = entry.Open()) { var manifest = ManifestReader.Read(manifestStream); var module = AbstractTypeFactory <ManifestModuleInfo> .TryCreateInstance(); module.LoadFromManifest(manifest); var alreadyExistModule = _externalModuleCatalog.Modules.OfType <ManifestModuleInfo>().FirstOrDefault(x => x.Equals(module)); if (alreadyExistModule != null) { module = alreadyExistModule; } else { //Force dependency validation for new module _externalModuleCatalog.CompleteListWithDependencies(new[] { module }).ToList().Clear(); _externalModuleCatalog.AddModule(module); } module.Ref = targetFilePath; result = new ModuleDescriptor(module); } } } } return(Ok(result)); }
public async Task ReplayRecording() { using (Database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context)) { if (HttpContext.Request.HasFormContentType == false) { HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; await using (var writer = new AsyncBlittableJsonTextWriter(context, ResponseBodyStream())) { context.Write(writer, new DynamicJsonValue { ["Type"] = "Error", ["Error"] = "Transactions replay requires form content type" }); return; } } var operationId = GetLongQueryString("operationId", false) ?? Database.Operations.GetNextOperationId(); using (var operationCancelToken = CreateOperationToken()) { var result = await Database.Operations.AddOperation( database : Database, description : "Replay transaction commands", operationType : Operations.Operations.OperationType.ReplayTransactionCommands, taskFactory : progress => Task.Run(async() => { var reader = new MultipartReader(MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(HttpContext.Request.ContentType), MultipartRequestHelper.MultipartBoundaryLengthLimit), HttpContext.Request.Body); while (true) { var section = await reader.ReadNextSectionAsync().ConfigureAwait(false); if (section == null) { break; } if (ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out ContentDispositionHeaderValue contentDisposition) == false) { continue; } if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { if (section.Headers.ContainsKey("Content-Encoding") && section.Headers["Content-Encoding"] == "gzip") { await using (var gzipStream = new GZipStream(section.Body, CompressionMode.Decompress)) { return(await DoReplayAsync(progress, gzipStream, operationCancelToken.Token)); } } return(await DoReplayAsync(progress, section.Body, operationCancelToken.Token)); } } throw new BadRequestException("Please upload source file using FormData"); }), id : operationId, token : operationCancelToken ); await using (var writer = new AsyncBlittableJsonTextWriter(context, ResponseBodyStream())) { context.Write(writer, result.ToJson()); } } } }
public async Task <ActionResult <ContentItem[]> > UploadContent(string contentType, string storeId, [FromQuery] string folderUrl, [FromQuery] string url = null) { if (url == null && !MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { return(BadRequest($"Expected a multipart request, but got {Request.ContentType}")); } var retVal = new List <ContentFile>(); var storageProvider = _blobContentStorageProviderFactory.CreateProvider(GetContentBasePath(contentType, storeId)); if (url != null) { var fileName = HttpUtility.UrlDecode(Path.GetFileName(url)); var fileUrl = folderUrl + "/" + fileName; using (var client = new WebClient()) using (var blobStream = storageProvider.OpenWrite(fileUrl)) using (var remoteStream = client.OpenRead(url)) { remoteStream.CopyTo(blobStream); var сontentFile = AbstractTypeFactory <ContentFile> .TryCreateInstance(); сontentFile.Name = fileName; сontentFile.Url = storageProvider.GetAbsoluteUrl(fileUrl); retVal.Add(сontentFile); } } else { var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, HttpContext.Request.Body); var section = await reader.ReadNextSectionAsync(); if (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { var fileName = contentDisposition.FileName.Value ?? contentDisposition.Name.Value.Replace("\"", string.Empty); var targetFilePath = folderUrl + "/" + fileName; using (var targetStream = storageProvider.OpenWrite(targetFilePath)) { await section.Body.CopyToAsync(targetStream); } var contentFile = AbstractTypeFactory <ContentFile> .TryCreateInstance(); contentFile.Name = fileName; contentFile.Url = storageProvider.GetAbsoluteUrl(targetFilePath); retVal.Add(contentFile); } } } ContentCacheRegion.ExpireContent(($"content-{storeId}")); return(Ok(retVal.ToArray())); }
public static async Task <FormValueProvider> StreamFileAsync(this HttpRequest request, Stream targetStream, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); 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(cancellationToken); while (section != null) { ContentDispositionHeaderValue contentDisposition; var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { formAccumulator.Append("fileName", contentDisposition.FileName.Value); await section.Body.CopyToAsync(targetStream, 81920, cancellationToken); } 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); 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(cancellationToken); } // Bind form data to a model var formValueProvider = new FormValueProvider(BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture); return(formValueProvider); }
public static async Task <string> Start(HttpRequest request, FormOptions options) { if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType)) { return(null); } // 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), options.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)) { //targetFilePath = Path.GetTempFileName(); targetFilePath = System.IO.Path.Combine(Utils.Constants.TEMP_PATH, contentDisposition.FileName.Value.Replace("\"", "")); using (var targetStream = System.IO.File.Create(targetFilePath)) { 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); if (formAccumulator.ValueCount > options.ValueCountLimit) { throw new InvalidDataException($"Form key count limit {options.ValueCountLimit} exceeded."); } } } } // Drains any remaining section body that has not been consumed and // reads the headers for the next section. section = await reader.ReadNextSectionAsync(); } return(targetFilePath); }
public async Task <Unit> Handle(ImportExcelFileCommand request, CancellationToken cancellationToken) { string fullPath = null; List <City> cities = new List <City> (); List <Sale> sales = new List <Sale> (); var boundary = MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(request.context.Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, request.context.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)) { string folderName = "TempExcels"; string webRootPath = hostingEnvironment.ContentRootPath; string newPath = Path.Combine(webRootPath, folderName); if (!Directory.Exists(newPath)) { Directory.CreateDirectory(newPath); } fullPath = Path.Combine(newPath, "testdata.xlsx"); var targetStream = System.IO.File.Create(fullPath); await section.Body.CopyToAsync(targetStream); ISheet citySheet, saleSheet; await targetStream.FlushAsync(); targetStream.Seek(0, SeekOrigin.Begin); XSSFWorkbook hssfwb = new XSSFWorkbook(targetStream); //This will read 2007 Excel format citySheet = hssfwb.GetSheet("Cities"); saleSheet = hssfwb.GetSheet("Sales"); //get first sheet from workbook for (int i = (citySheet.FirstRowNum + 1); i <= citySheet.LastRowNum; i++) //Read Excel File { IRow row = citySheet.GetRow(i); if (row == null) { continue; } cities.Add(new City() { Name = row.GetCell(0).StringCellValue }); } cities = await repository.AddCities(cities); for (int i = (saleSheet.FirstRowNum + 1); i <= saleSheet.LastRowNum; i++) //Read Excel File { IRow row = saleSheet.GetRow(i); if (row == null) { continue; } sales.Add(new Sale() { CityId = cities.First(c => c.Name == row.GetCell(0).StringCellValue).Id, UserName = row.GetCell(1).StringCellValue, ProductName = row.GetCell(2).StringCellValue, ProductId = row.GetCell(3).StringCellValue, Price = (long)row.GetCell(4).NumericCellValue, }); } if (sales.Count > 0) { await repository.AddSales(sales); } } } // Drains any remaining section body that has not been consumed and // reads the headers for the next section. section = await reader.ReadNextSectionAsync(); } return(Unit.Value); }
public async Task <IActionResult> uploads() { if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { return(BadRequest($"Expected a multipart request, but got {Request.ContentType}")); } StringValues UserName; SiteConfig.HttpContextAccessor.HttpContext.Request.Headers.TryGetValue("UName", out UserName); // 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(); var uploadPath = SiteConfig.Environment.ContentRootPath + DirectoryPaths.BlogsPhotoDirectoryPath; if (!Directory.Exists(uploadPath)) { Directory.CreateDirectory(uploadPath); Directory.CreateDirectory(uploadPath + "thumbs/"); } var fileName = ""; while (section != null) { ContentDispositionHeaderValue contentDisposition; var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition); if (hasContentDispositionHeader) { if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)) { var output = formAccumulator.GetResults(); var chunk = "0"; foreach (var item in output) { if (item.Key == "name") { fileName = UtilityBLL.ReplaceSpaceWithHyphin(Path.GetFileNameWithoutExtension(item.Value)) + "-" + Guid.NewGuid().ToString().Substring(0, 10) + Path.GetExtension(item.Value); } else if (item.Key == "chunk") { chunk = item.Value; } } var strPath = uploadPath + "" + fileName; using (var fs = new FileStream(strPath, chunk == "0" ? FileMode.Create : FileMode.Append)) { await section.Body.CopyToAsync(fs); fs.Flush(); } } 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."); } } } } var result = formAccumulator.GetResults(); // Drains any remaining section body that has not been consumed and // reads the headers for the next section. section = await reader.ReadNextSectionAsync(); } string orignalfilename = uploadPath + "" + fileName; string thumbfilename = uploadPath + "thumbs/" + fileName; try { Jugnoon.Utility.Image.Generate_Thumbs(orignalfilename, thumbfilename, "", Jugnoon.Blogs.Configs.BlogSettings.thumbnail_width, Jugnoon.Blogs.Configs.BlogSettings.thumbnail_height, 0, 0, Jugnoon.Settings.Configs.MediaSettings.quality); string url = Config.GetUrl("contents/blogs/thumbs/" + fileName); string fileType = System.IO.Path.GetExtension(fileName); string fileIndex = fileName.Replace(fileType, ""); return(Ok(new { jsonrpc = "2.0", result = "OK", fname = fileName, url = url, filetype = fileType, filename = fileName, fileIndex = fileIndex })); } catch (Exception ex) { return(Ok(new { jsonrpc = "2.0", result = "OK", message = ex.Message, attempt = 2 })); } }
public async Task <IActionResult> UploadPhysical() { if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) { ModelState.AddModelError("File", $"The request couldn't be processed (Error 1)."); // Log error return(BadRequest(ModelState)); } 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) { // This check assumes that there's a file // present without form data. If form data // is present, this method immediately fails // and returns the model error. if (!MultipartRequestHelper .HasFileContentDisposition(contentDisposition)) { ModelState.AddModelError("File", $"The request couldn't be processed (Error 2)."); // Log error return(BadRequest(ModelState)); } else { // Don't trust the file name sent by the client. To display // the file name, HTML-encode the value. var trustedFileNameForDisplay = WebUtility.HtmlEncode( contentDisposition.FileName.Value); var trustedFileNameForFileStorage = Path.GetRandomFileName(); // **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. var streamedFileContent = await FileHelpers.ProcessStreamedFile( section, contentDisposition, ModelState, _permittedExtensions, _fileSizeLimit); if (!ModelState.IsValid) { return(BadRequest(ModelState)); } using (var targetStream = System.IO.File.Create( Path.Combine(_targetFilePath, trustedFileNameForFileStorage))) { await targetStream.WriteAsync(streamedFileContent); _logger.LogInformation( $"Uploaded file '{trustedFileNameForDisplay}' saved to " + $"'{_targetFilePath}' as {trustedFileNameForFileStorage}"); } } } // Drain any remaining section body that hasn't been consumed and // read the headers for the next section. section = await reader.ReadNextSectionAsync(); } return(Created(nameof(StreamingController), null)); }
public static async Task <FormValueProvider> StreamFile(this HttpRequest request, Stream targetStream, int bufferSize) { 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. KeyValueAccumulator formAccumulator = new KeyValueAccumulator(); // string targetFilePath = null; string boundary = MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); MultipartReader reader = new MultipartReader(boundary, request.Body); MultipartSection section = await reader.ReadNextSectionAsync(); while (section != null) { bool hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out ContentDispositionHeaderValue 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. Microsoft.Extensions.Primitives.StringSegment key = HeaderUtilities.RemoveQuotes(contentDisposition.Name); Encoding encoding = GetEncoding(section); using (StreamReader streamReader = new StreamReader( section.Body, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: bufferSize, leaveOpen: true)) { // The value length limit is enforced by MultipartBodyLengthLimit string 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 FormValueProvider formValueProvider = new FormValueProvider( BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture); return(formValueProvider); }