private Dictionary <string, StringValues> ReadHeaders() { int totalSize = 0; var accumulator = new KeyMultValuesPair(); var line = _stream.ReadLine(HeadersLengthLimit - totalSize); while (!string.IsNullOrEmpty(line)) { if (HeadersLengthLimit - totalSize < line.Length) { throw new InvalidDataException($"Multipart headers length limit {HeadersLengthLimit} exceeded."); } totalSize += line.Length; int splitIndex = line.IndexOf(':'); if (splitIndex <= 0) { throw new InvalidDataException($"Invalid header line: {line}"); } var name = line.Substring(0, splitIndex); var value = line.Substring(splitIndex + 1, line.Length - splitIndex - 1).Trim(); accumulator.Append(name, value); if (accumulator.KeyCount > HeadersCountLimit) { throw new InvalidDataException($"Multipart headers count limit {HeadersCountLimit} exceeded."); } line = _stream.ReadLine(HeadersLengthLimit - totalSize); } return(accumulator.GetResults()); }
/// <summary> /// 从Form中读取数据 /// </summary> /// <returns>包含已分析的 HTTP 窗体主体的集合</returns> public Dictionary <string, StringValues> ReadForm() { var accumulator = new KeyMultValuesPair(); while (!_endOfStream) { ReadNextPairImpl(); Append(ref accumulator); } return(accumulator.GetResults()); }
/// <summary> /// 从Form中读取数据 /// </summary> /// <param name="cancellationToken"><see cref="CancellationToken"/>.</param> /// <returns>包含已分析的 HTTP 窗体主体的集合。 public async Task <Dictionary <string, StringValues> > ReadFormAsync(CancellationToken cancellationToken = new CancellationToken()) { var accumulator = new KeyMultValuesPair(); while (!_endOfStream) { await ReadNextPairAsyncImpl(cancellationToken); Append(ref accumulator); } return(accumulator.GetResults()); }
private IFormCollection InnerReadForm() { if (!HasFormContentType) { throw new InvalidOperationException("Incorrect Content-Type: " + _request.ContentType); } 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.RequestStream, encoding) { ValueCountLimit = _options.ValueCountLimit, KeyLengthLimit = _options.KeyLengthLimit, ValueLengthLimit = _options.ValueLengthLimit, }) { formFields = new FormCollection(formReader.ReadForm()); } } else if (HasMultipartFormContentType(contentType)) { var formAccumulator = new KeyMultValuesPair(); var boundary = GetBoundary(contentType, _options.MultipartBoundaryLengthLimit); var multipartReader = new MultipartReader(boundary, _request.RequestStream) { HeadersCountLimit = _options.MultipartHeadersCountLimit, HeadersLengthLimit = _options.MultipartHeadersLengthLimit, BodyLengthLimit = _options.MultipartBodyLengthLimit, }; var section = multipartReader.ReadNextSection(); while (section != null) { // Parse the content disposition here and pass it further to avoid reparsings ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out ContentDispositionHeaderValue contentDisposition); if (contentDisposition.IsFileDisposition()) { var fileSection = new FileMultipartSection(section, contentDisposition); // Enable buffering for the file if not already done for the full body section.EnableRewind( _request.HttpContext.Response.RegisterForDispose, _options.MemoryBufferThreshold, _options.MultipartBodyLengthLimit); // Find the end section.Body.Drain(); var name = fileSection.Name; var fileName = fileSection.FileName; FormFile file; if (section.BaseStreamOffset.HasValue) { // Relative reference to buffered request body file = new FormFile(_request.RequestStream, 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 NameValueCollection().Create(section.Headers.Select(x => new KeyValuePair <string, string>(x.Key, x.Value.ContvertToString()))); if (files == null) { files = new FormFileCollection(); } if (files.Count >= _options.ValueCountLimit) { throw new InvalidDataException($"Form value count limit {_options.ValueCountLimit} exceeded."); } files.Add(file); } else if (contentDisposition.IsFormDisposition()) { var formDataSection = new FormMultipartSection(section, contentDisposition); // Content-Disposition: form-data; name="key" // // value // Do not limit the key name length here because the mulipart headers length limit is already in effect. var key = formDataSection.Name; var value = formDataSection.GetValue(); 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 = multipartReader.ReadNextSection(); } if (formAccumulator.HasValues) { formFields = new FormCollection(formAccumulator.GetResults(), files); } } //} // Rewind so later readers don't have to. if (_request.RequestStream.CanSeek) { _request.RequestStream.Seek(0, SeekOrigin.Begin); } if (formFields != null) { Form = formFields; } else if (files != null) { Form = new FormCollection(null, files); } else { Form = FormCollection.Empty; } return(Form); }