Exemple #1
0
        /// <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;

            string contentType;
            string contentFileName = null;
            long   fileSize        = 0;

            if (MultipartRequestHelper.IsMultipartContentType(request.ContentType))
            {
                // Only read the first section of the Multipart message.
                MediaTypeHeaderValue mediaType = MediaTypeHeaderValue.Parse(request.ContentType);
                string boundary = MultipartRequestHelper.GetBoundary(mediaType, _defaultFormOptions.MultipartBoundaryLengthLimit);

                MultipartReader  reader  = new MultipartReader(boundary, request.Body);
                MultipartSection 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> contentDispositionValues = contentDisposition.Split(';').ToList();

                    string fileNameValue = contentDispositionValues.FirstOrDefault(x => x.Contains("filename", StringComparison.CurrentCultureIgnoreCase));

                    if (!string.IsNullOrEmpty(fileNameValue))
                    {
                        string[] valueParts = fileNameValue.Split('=');

                        if (valueParts.Length == 2)
                        {
                            contentFileName = HttpUtility.UrlDecode(valueParts[1]);
                        }
                    }
                }

                contentType = request.ContentType;
            }

            string user = User.GetUserOrOrgId();

            DataElement newData = DataElementHelper.CreateDataElement(elementType, refs, instance, creationTime, contentType, contentFileName, fileSize, user);

            return(theStream, newData);
        }
Exemple #2
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseAuthentication();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });

            app.Use(async(context, next) =>
            {
                if (!IsMultipartContentType(context.Request.ContentType))
                {
                    await next();
                    return;
                }

                var boundary = GetBoundary(context.Request.ContentType);
                var reader   = new MultipartReader(boundary, context.Request.Body);
                var section  = await reader.ReadNextSectionAsync();

                while (section != null)
                {
                    // process each image
                    const int chunkSize = 1024;
                    var buffer          = new byte[chunkSize];
                    var bytesRead       = 0;
                    var fileName        = GetFileName(section.ContentDisposition);

                    using (var stream = new FileStream(fileName, FileMode.Append))
                    {
                        do
                        {
                            bytesRead = await section.Body.ReadAsync(buffer, 0, buffer.Length);
                            stream.Write(buffer, 0, bytesRead);
                        } while (bytesRead > 0);
                    }

                    section = await reader.ReadNextSectionAsync();
                }

                context.Response.WriteAsync("Done.");
            });
        }
Exemple #3
0
        /// <summary>
        /// Read the next multipart section
        /// </summary>
        /// <param name="reader">The reader to parse with.</param>
        /// <param name="async">
        /// Whether to invoke the operation asynchronously.
        /// </param>
        /// <param name="cancellationToken">
        /// Optional <see cref="CancellationToken"/> to propagate notifications
        /// that the operation should be cancelled.
        /// </param>
        /// <returns>The next multipart section.</returns>
        internal static async Task <MultipartSection> GetNextSectionAsync(
            this MultipartReader reader,
            bool async,
            CancellationToken cancellationToken) =>
        async ?
        await reader.ReadNextSectionAsync(cancellationToken).ConfigureAwait(false) :
#pragma warning disable AZC0102
        reader.ReadNextSectionAsync(cancellationToken).GetAwaiter().GetResult();         // #7972: Decide if we need a proper sync API here
Exemple #4
0
        /// <summary>
        /// Read the next multipart section
        /// </summary>
        /// <param name="reader">The reader to parse with.</param>
        /// <param name="async">
        /// Whether to invoke the operation asynchronously.
        /// </param>
        /// <param name="cancellationToken">
        /// Optional <see cref="CancellationToken"/> to propagate notifications
        /// that the operation should be cancelled.
        /// </param>
        /// <returns>The next multipart section.</returns>
        internal static async Task <MultipartSection> GetNextSectionAsync(
            this MultipartReader reader,
            bool async,
            CancellationToken cancellationToken) =>
        async ?
        await reader.ReadNextSectionAsync(cancellationToken).ConfigureAwait(false) :
#pragma warning disable AZC0102                                                  // Do not use GetAwaiter().GetResult(). Use the TaskExtensions.EnsureCompleted() extension method instead.
        reader.ReadNextSectionAsync(cancellationToken).GetAwaiter().GetResult(); // #7972: Decide if we need a proper sync API here
Exemple #5
0
        public async Task <IActionResult> UploadImages([FromRoute] string propertyId)
        {
            var boundary = GetBoundary(Request.ContentType);

            if (boundary == null)
            {
                if (await this.imageService.UploadFileToStorageAsync(Request.Body, propertyId, Guid.NewGuid().ToString()))
                {
                    return(this.Ok());
                }
                return(this.BadRequest());
            }

            var reader = new MultipartReader(boundary, Request.Body, 80 * 1024);
            MultipartSection section;

            using (Stream stream = new MemoryStream())
            {
                while ((section = await reader.ReadNextSectionAsync()) != null)
                {
                    var contentDispo = section.GetContentDispositionHeader();

                    if (contentDispo.IsFileDisposition())
                    {
                        var    fileSection = section.AsFileSection();
                        var    bufferSize  = 32 * 1024;
                        byte[] buffer      = new byte[bufferSize];

                        if (stream.Position != 0)
                        {
                            return(BadRequest("Only one file is accepted per request."));
                        }

                        await fileSection.FileStream.CopyToAsync(stream);
                    }
                    else if (contentDispo.IsFormDisposition())
                    {
                        return(BadRequest("Only one file is accepted per request."));
                    }
                    else
                    {
                        return(BadRequest("Malformatted message body."));
                    }
                }

                if (stream == null)
                {
                    return(BadRequest("No file submitted."));
                }

                stream.Seek(0, SeekOrigin.Begin);
                if (await this.imageService.UploadFileToStorageAsync(stream, propertyId, Guid.NewGuid().ToString()))
                {
                    return(this.Ok());
                }
                return(this.BadRequest());
            }
        }
            public async Task <Response> Handle(Request request, CancellationToken cancellationToken)
            {
                var httpContext        = _httpContextAccessor.HttpContext;
                var defaultFormOptions = new FormOptions();
                var digitalAssets      = new List <DigitalAsset>();

                if (!MultipartRequestHelper.IsMultipartContentType(httpContext.Request.ContentType))
                {
                    throw new Exception($"Expected a multipart request, but got {httpContext.Request.ContentType}");
                }

                var mediaTypeHeaderValue = MediaTypeHeaderValue.Parse(httpContext.Request.ContentType);

                var boundary = MultipartRequestHelper.GetBoundary(
                    mediaTypeHeaderValue,
                    defaultFormOptions.MultipartBoundaryLengthLimit);

                var reader = new MultipartReader(boundary, httpContext.Request.Body);

                var section = await reader.ReadNextSectionAsync();

                while (section != null)
                {
                    DigitalAsset digitalAsset = default;

                    var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out ContentDispositionHeaderValue contentDisposition);

                    if (hasContentDispositionHeader)
                    {
                        if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                        {
                            using (var targetStream = new MemoryStream())
                            {
                                await section.Body.CopyToAsync(targetStream);

                                var name        = $"{contentDisposition.FileName}".Trim(new char[] { '"' }).Replace("&", "and");
                                var bytes       = StreamHelper.ReadToEnd(targetStream);
                                var contentType = section.ContentType;

                                digitalAsset = new DigitalAsset(name, bytes, contentType);
                            }
                        }
                    }

                    _context.DigitalAssets.Add(digitalAsset);

                    digitalAssets.Add(digitalAsset);

                    section = await reader.ReadNextSectionAsync();
                }

                await _context.SaveChangesAsync(cancellationToken);

                return(new()
                {
                    DigitalAssetIds = digitalAssets.Select(x => x.DigitalAssetId).ToList()
                });
            }
        /// <summary>
        /// This api is to download the File from the Flite, This is called by intermediate service as FileReader Services.
        /// FileReader Services is read the file from flite and privide to this API by multipartFormDatacontent.
        /// </summary>
        /// <param name="id">File Id</param>
        /// <param name="fliteNo">Flite No</param>
        /// <param name="req">MultiPart Reader data consist of header, body etc...</param>
        /// <returns></returns>
        private async Task <FileUpload> UploadFile(string id, string fliteNo, HttpRequest req)
        {
            var boundary             = HeaderUtilities.RemoveQuotes(MediaTypeHeaderValue.Parse(req.ContentType).Boundary);
            var reader               = new MultipartReader(boundary.Value, req.Body);
            MultipartSection section = await reader.ReadNextSectionAsync();

            string fileId = string.Empty;

            while (section != null)
            {
                ContentDispositionHeaderValue contentDisposition;
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);
                if (string.IsNullOrEmpty(fileId) == false)
                {
                    break;
                }

                fileId = $"NameofFile:  {fliteNo}{id}";
                var filePath = "FilePath" + fileId;
                _fileRep.Initialize(filePath);
            }
            try
            {
                var encoding = GetEncoding(section);

                using (var streamReader = new BinaryReader(
                           section.Body,
                           encoding,
                           leaveOpen: true))
                {
                    while (true)
                    {
                        var bin = streamReader.ReadBytes(1024 * 1000 * 10);

                        if (bin.Length == 0)
                        {
                            break;
                        }

                        using (MemoryStream ms = new MemoryStream(bin))
                        {
                            _fileRep.UploadToBucket(ms);
                        }
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }

            section = await reader.ReadNextSectionAsync();

            return(new FileUpload()
            {
                FileId = fileId
            });
        }
Exemple #8
0
    public void MultipartReader_BufferSizeMustBeLargerThanBoundary_Throws()
    {
        var stream = MakeStream(ThreePartBody);

        Assert.Throws <ArgumentOutOfRangeException>(() =>
        {
            var reader = new MultipartReader(Boundary, stream, 5);
        });
    }
        public async Task <MultipartReader> GetMultipartReader(HttpRequest request)
        {
            FormOptions _defaultFormOptions = new FormOptions();
            var         boundary            = await Task.Run(() => MultipartRequest.GetBoundary(MediaTypeHeaderValue.Parse(request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit));

            var reader = new MultipartReader(boundary, request.Body);

            return(reader);
        }
Exemple #10
0
        // expected exception
        public virtual void TestParseHeaders()
        {
            string          testString = new string("\r\nFoo: Bar\r\n Header : Val ue ");
            MultipartReader reader     = new MultipartReader("multipart/related;boundary=X", null
                                                             );

            reader.ParseHeaders(testString);
            NUnit.Framework.Assert.AreEqual(reader.headers.Keys.Count, 2);
        }
        /// <summary>
        ///     Copy file stream to <paramref name="targetStream" /> and creates and returns an instance of
        ///     <typeparamref name="TDto" />
        ///     with properties fulfilled.
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="targetStream"></param>
        /// <typeparam name="TDto"></typeparam>
        /// <returns>Instance of <typeparamref name="TDto" /></returns>
        /// <exception cref="Exception"></exception>
        /// <exception cref="InvalidDataException"></exception>
        /// <exception cref="InvalidOperationException"></exception>
        public static async Task <TDto> ReadMultiPartFormData <TDto>(this ControllerBase controller, Stream targetStream)
            where TDto : class, new()
        {
            if (IsMultipartContentType(controller.Request.ContentType) == false)
            {
                throw new Exception($"Expected a multipart request, but got {controller.Request.ContentType}");
            }

            var boundary = MediaTypeHeaderValue.Parse(controller.Request.ContentType)
                           .GetBoundary(DefaultFormOptions.MultipartBoundaryLengthLimit);
            var reader = new MultipartReader(boundary, controller.Request.Body);

            var formAccumulator = new KeyValueAccumulator();

            var section = await reader.ReadNextSectionAsync();

            do
            {
                if (ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition))
                {
                    if (contentDisposition.HasFile())
                    {
                        await section.Body.CopyToAsync(targetStream);
                    }
                    else if (contentDisposition.HasFormData())
                    {
                        var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                        var encoding = GetEncoding(section);
                        using (var streamReader = new StreamReader(section.Body, encoding))
                        {
                            var value = await streamReader.ReadToEndAsync();

                            if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = string.Empty;
                            }

                            formAccumulator.Append(key.Value.Replace("[]", string.Empty), value);

                            if (formAccumulator.ValueCount > DefaultFormOptions.ValueCountLimit)
                            {
                                throw new InvalidDataException(
                                          $"Form key count limit {DefaultFormOptions.ValueCountLimit} exceeded.");
                            }
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("Content type invalid.");
                    }
                }

                section = await reader.ReadNextSectionAsync();
            } while (section != null);

            return(await GetModel <TDto>(controller, formAccumulator));
        }
Exemple #12
0
    public async Task MultipartReader_StripQuotesFromBoundary()
    {
        var stream = MakeStream(OnePartBody);
        var reader = new MultipartReader(BoundaryWithQuotes, stream);

        var section = await reader.ReadNextSectionAsync();

        Assert.NotNull(section);
    }
Exemple #13
0
        protected async Task <UploadModel> Upload()
        {
            var formOptions = new FormOptions();
            var result      = new UploadModel();

            result.Boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), formOptions.MultipartBoundaryLengthLimit);
            var reader  = new MultipartReader(result.Boundary, HttpContext.Request.Body);
            var section = (MultipartSection)null;

            while ((section = await reader.ReadNextSectionAsync()) != null)
            {
                if (ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition))
                {
                    if (MultipartRequestHelper.HasFile(contentDisposition))
                    {
                        result.FileName = contentDisposition.FileName.ToString();
                        result.Stream   = section.Body;
                        return(result);
                    }
                    else if (MultipartRequestHelper.HasModel(contentDisposition))
                    {
                        using (var factory = new DBItemConverterFactory(HttpContext))
                        {
                            var option = new JsonSerializerOptions();
                            option.InitDefaults(factory);
                            result.Model = await JsonSerializer.DeserializeAsync <T>(section.Body, option);
                        }
                    }
                    else if (MultipartRequestHelper.HasFormData(contentDisposition))
                    {
                        var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                        var encoding = MultipartRequestHelper.GetEncoding(section);
                        using (var streamReader = new StreamReader(section.Body, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: 2048, leaveOpen: true))
                        {
                            // The value length limit is enforced by MultipartBodyLengthLimit
                            var value = await streamReader.ReadToEndAsync();

                            if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = String.Empty;
                            }
                            if (StringSegment.Equals(key, "LastWriteTime", StringComparison.OrdinalIgnoreCase) &&
                                DateTime.TryParseExact(value, "o", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var lastWriteTime))
                            {
                                result.ModificationDate = lastWriteTime;
                            }
                            else
                            {
                                result.Content[key.ToString()] = value;
                            }
                        }
                    }
                }
            }
            return(result);
        }
        internal async Task ImportStream(MultipartSection section)
        {
            var reader          = new MultipartReader("++++++++", section.Body);
            var templateSection = await reader.ReadNextSectionAsync();

            var template = await ReadTemplate(templateSection);

            var recordType = Assembly.GetAssembly(typeof(IBlazeEntity))?.ExportedTypes.FirstOrDefault(t => t.Name.Equals(template.TableName()));

            if (recordType == null)
            {
                throw new InvalidOperationException($"Cannot import records into object of type {template.TableName()}.");
            }

            var importSection = await reader.ReadNextSectionAsync();

            using var stream = new StreamReader(importSection.Body);
            var config = template.CreateConfiguration(_logger);

            using var rdr = new CsvReader(stream, config);

            var records = rdr.GetRecords(recordType);

            switch (recordType.Name)
            {
            case "Portfolio":
                await _repository.SaveAsync(records.OfType <Portfolio>().ToList(), default, From);

                break;

            case "TaxLot":
                await _repository.SaveAsync(records.OfType <TaxLot>().ToList(), default, From);

                break;

            case "Security":
                await _repository.SaveAsync(records.OfType <Security>().ToList(), default, From);

                break;

            case "Order":
                await _repository.SaveAsync(records.OfType <Order>().ToList(), default, From);

                break;

            case "Model":
                await _repository.SaveAsync(records.OfType <Model>().ToList(), default, From);

                break;

            case "Allocation":
                await _repository.SaveAsync(records.OfType <Allocation>().ToList(), default, From);

                break;
            }
        }
        public async Task <ResponseModel> Handle(MultipleFileUploadCommand request, CancellationToken cancellationToken)
        {
            var errorModel = new FormFileErrorModel();

            if (!MultipartRequestHelper.IsMultipartContentType(_accessor.HttpContext.Request.ContentType))
            {
                errorModel.Errors.Add("File",
                                      $"The request couldn't be processed (Error 1).");

                return(ResponseProvider.Ok(errorModel));
            }
            var boundary = MultipartRequestHelper.GetBoundary(
                MediaTypeHeaderValue.Parse(_accessor.HttpContext.Request.ContentType),
                _defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader  = new MultipartReader(boundary, _accessor.HttpContext.Request.Body);
            var section = await reader.ReadNextSectionAsync(cancellationToken);

            while (section != null)
            {
                var hasContentDispositionHeader =
                    ContentDispositionHeaderValue.TryParse(
                        section.ContentDisposition, out var contentDisposition);

                if (hasContentDispositionHeader)
                {
                    if (!MultipartRequestHelper
                        .HasFileContentDisposition(contentDisposition))
                    {
                        errorModel.Errors.Add("File", $"The request couldn't be processed (Error 2).");

                        return(ResponseProvider.Ok(errorModel));
                    }
                    else
                    {
                        var streamedFileContent = await FileHelpers.ProcessStreamedFile(
                            section, contentDisposition, errorModel,
                            _permittedExtensions, _streamFileLimitSize, ValidateExtension.Encrypt);

                        if (errorModel.Errors.Any())
                        {
                            return(ResponseProvider.Ok(errorModel));
                        }
                        var fileName = FileHelpers.GetFileName(section.ContentDisposition);

                        var fileNameWithEncryptExtension = UploadFileHelper.GetFileNameWithEncryptExtension(fileName, request.EncryptAlg);
                        var uploadFileAbsolutePath       = UploadFileHelper.GetUploadAbsolutePath(_contentRootPath, fileNameWithEncryptExtension, request.Archive);

                        await UploadFile(streamedFileContent, uploadFileAbsolutePath, request.EncryptAlg);
                    }
                }

                section = await reader.ReadNextSectionAsync(cancellationToken);
            }

            return(ResponseProvider.Ok("Upload file successfully"));
        }
        public async Task <IActionResult> ReceiveFile()
        {
            if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
            {
                throw new Exception("Not a multipart request");
            }

            var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader   = new MultipartReader(boundary, Request.Body);

            // note: this is for a single file, you could also process multiple files
            var section = await reader.ReadNextSectionAsync();

            if (section == null)
            {
                return(BadRequest());
            }

            Request.Headers.TryGetValue("Description", out Microsoft.Extensions.Primitives.StringValues videoDesecription);

            var i = 0;

            do
            {
                if (!ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition))
                {
                    throw new Exception("No content disposition in multipart defined");
                }

                var fileName2 = contentDisposition.FileNameStar.ToString();
                if (string.IsNullOrEmpty(fileName2))
                {
                    fileName2 = contentDisposition.FileName.ToString();
                }

                using var fileStream = section.Body;

                var uri = await _azureRepo.NewBlobFromStream(fileStream, "videos", fileName2);

                await _videoRepo.AddVideo(new Media()
                {
                    FullFileName = uri.ToString(), DisplayName = fileName2 + " " + videoDesecription, Type = contentDisposition.Name.Value
                });

                //media.Type = "image/" + file.FileName.Split('.').Last();
                //media.DisplayName = file.FileName;
                //media.FullFileName = "/upload/image/" + file.FileName;

                i++;
                section = await reader.ReadNextSectionAsync();
            } while (section != null);

            //await SendFileSomewhere(fileStream);

            return(Ok());
        }
        public async Task <int> ReadMultipart()
        {
            var counter = 0;

            using (var body = GetPayload())
            {
                var reader = new MultipartReader(Boundary, body);
                HttpApplicationRequestSection section;
                while ((section = await reader
                                  .ReadNextHttpApplicationRequestSectionAsync(default, false, CancellationToken.None)
Exemple #18
0
    private async Task StoreAsyncCore(FileIdentifier id, MultipartReader reader, CancellationToken cancellationToken)
    {
        // We need to manually read each part of the request. The browser may do as it likes and send whichever part first,
        // which means we have to build up the metadata incrementally and can only write it later

        UploadContext  uploadContext = new UploadContext(id);
        StoredMetadata?metadata      = null;

        try {
            MultipartSection section = await reader.ReadNextSectionAsync(cancellationToken);

            while (section != null)
            {
                await this.ProcessSectionAsync(uploadContext, section, cancellationToken);

                section = await reader.ReadNextSectionAsync(cancellationToken);
            }

            if (uploadContext.MetadataFactory.IsComplete())
            {
                metadata = uploadContext.MetadataFactory.Build();
            }

            if (metadata == null)
            {
                throw new InvalidOperationException("Metadata is incomplete - file is not uploaded or expiration missing");
            }

            await this.StoreMetadataAsync(id, metadata, cancellationToken);

            this._logger.LogInformation(LogEvents.NewUpload, "Completed: New upload of file {0} to id {1} [{2:s}]", metadata.OriginalFileName, id, DateTime.UtcNow);
        }
        catch (OperationCanceledException ex) {
            this._logger.LogWarning(LogEvents.UploadCancelled, ex, "Upload failed due to cancellation");

            this.TryCleanup(id);

            // No use rethrowing the exception, we're done anyway.
        }
        catch (InvalidDataException ex) {
            this._logger.LogError(LogEvents.UploadFailed, ex, "Upload failed due to file size exceeding");

            this.TryCleanup(id);

            throw new UploadFailedException("File size exceeded of " + reader.BodyLengthLimit.GetValueOrDefault().Bytes().Megabytes);
        }
        catch (Exception ex) when(!(ex is UploadCryptoArgumentOrderException))
        {
            this._logger.LogError(LogEvents.UploadFailed, ex, "Upload failed due to exception");

            this.TryCleanup(id);

            throw new UploadFailedException("Unable to complete upload", ex);
        }
    }
Exemple #19
0
        public async Task <ActionResult <BlobInfo[]> > UploadAssetToLocalFileSystemAsync()
        {
            //ToDo Now supports downloading one file, find a solution for downloading multiple files
            // https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-3.1
            var result = new List <BlobInfo>();

            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);
            }

            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 = Path.Combine(uploadPath, fileName);

                        if (!Directory.Exists(uploadPath))
                        {
                            Directory.CreateDirectory(uploadPath);
                        }

                        using (var targetStream = System.IO.File.Create(targetFilePath))
                        {
                            await section.Body.CopyToAsync(targetStream);
                        }

                        var blobInfo = AbstractTypeFactory <BlobInfo> .TryCreateInstance();

                        blobInfo.Name = fileName;
                        //Use only file name as Url, for further access to these files need use PlatformOptions.LocalUploadFolderPath
                        blobInfo.Url         = fileName;
                        blobInfo.ContentType = MimeTypeResolver.ResolveContentType(fileName);
                        result.Add(blobInfo);
                    }
                }
            }
            return(Ok(result.ToArray()));
        }
Exemple #20
0
            public async Task <Response> Handle(Request request, CancellationToken cancellationToken)
            {
                var digitalAssets = new HashSet <DigitalAssetApiModel>();

                if (!MultipartRequestHelper.IsMultipartContentType(_httpContext.Request.ContentType))
                {
                    throw new Exception($"Expected a multipart request, but got {_httpContext.Request.ContentType}");
                }

                var boundary = MultipartRequestHelper.GetBoundary(
                    MediaTypeHeaderValue.Parse(_httpContext.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))
                        {
                            using (var targetStream = new MemoryStream())
                            {
                                await section.Body.CopyToAsync(targetStream);

                                var bytes  = StreamHelper.ReadToEnd(targetStream);
                                var tenant = await _context.Tenants.FindAsync(new Guid(_httpContext.Request.GetHeaderValue("Tenant")));

                                var digitalAsset = new DigitalAsset();
                                digitalAsset.Tenant      = tenant;
                                digitalAsset.FileName    = $"{contentDisposition.FileName}".Trim(new char[] { '"' }).Replace("&", "and");
                                digitalAsset.Name        = digitalAsset.FileName;
                                digitalAsset.Bytes       = bytes;
                                digitalAsset.ContentType = section.ContentType;
                                digitalAsset.UploadedOn  = DateTime.UtcNow;
                                _context.DigitalAssets.Add(digitalAsset);
                                await _context.SaveChangesAsync(cancellationToken, request.Username);

                                digitalAssets.Add(DigitalAssetApiModel.FromDigitalAsset(digitalAsset));
                            }
                        }
                    }

                    section = await reader.ReadNextSectionAsync();
                }

                return(new Response()
                {
                });
            }
Exemple #21
0
        public async Task <IActionResult> UploadImageLarge()
        {
            try
            {
                if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
                {
                    return(BadRequest(string.Format(MessagesConstants.ExpectedDifferentRequest, 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);
                            }
                        }
                        else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                        {
                            formAccumulator = await UploadImageLargeRefactor(formAccumulator, section, contentDisposition);
                        }
                    }

                    // Drains any remaining section body that has not been consumed and
                    // reads the headers for the next section.
                    section = await reader.ReadNextSectionAsync();
                }

                return(Ok(new ApiResponse(Microsoft.AspNetCore.Http.StatusCodes.Status200OK, true, "Image Uploaded Successfully.", targetFilePath)));
            }
            catch (Exception ex)
            {
                HttpContext.RiseError(new Exception(string.Concat("API := (Image := UploadImageLarge)", ex.Message, " Stack Trace : ", ex.StackTrace, " Inner Exception : ", ex.InnerException)));
                return(Ok(someIssueInProcessing));
            }
        }
        internal AspNetCoreMultipartReader(
            string contentType,
            Stream body,
            ISeekableStreamConverter seekableStreamConverter,
            IOptions <StoreConfiguration> storeConfiguration)
        {
            EnsureArg.IsNotNull(contentType, nameof(contentType));
            EnsureArg.IsNotNull(body, nameof(body));
            EnsureArg.IsNotNull(seekableStreamConverter, nameof(seekableStreamConverter));
            EnsureArg.IsNotNull(storeConfiguration?.Value, nameof(storeConfiguration));

            _seekableStreamConverter = seekableStreamConverter;
            _storeConfiguration      = storeConfiguration;

            if (!MediaTypeHeaderValue.TryParse(contentType, out MediaTypeHeaderValue media) ||
                !media.MediaType.Equals(KnownContentTypes.MultipartRelated, StringComparison.InvariantCultureIgnoreCase))
            {
                throw new UnsupportedMediaTypeException(
                          string.Format(CultureInfo.InvariantCulture, DicomApiResource.UnsupportedContentType, contentType));
            }

            string boundary = HeaderUtilities.RemoveQuotes(media.Boundary).ToString();

            if (string.IsNullOrWhiteSpace(boundary))
            {
                throw new UnsupportedMediaTypeException(
                          string.Format(CultureInfo.InvariantCulture, DicomApiResource.InvalidMultipartContentType, contentType));
            }

            // Check to see if the root content type was specified or not.
            if (media.Parameters != null)
            {
                foreach (NameValueHeaderValue parameter in media.Parameters)
                {
                    if (TypeParameterName.Equals(parameter.Name.ToString(), StringComparison.OrdinalIgnoreCase))
                    {
                        _rootContentType = HeaderUtilities.RemoveQuotes(parameter.Value).ToString();
                    }
                    else if (StartParameterName.Equals(parameter.Name.ToString(), StringComparison.OrdinalIgnoreCase))
                    {
                        // TODO: According to RFC2387 3.2, the root section can be specified by using the
                        // start parameter. For now, we will assume that the first section is the "root" section
                        // and will add support later. Throw exception in case start is specified.
                        throw new NotSupportedException(DicomApiResource.StartParameterIsNotSupported);
                    }
                }
            }

            _multipartReader = new MultipartReader(boundary, body)
            {
                // set the max length of each section in bytes
                BodyLengthLimit = _storeConfiguration.Value.MaxAllowedDicomFileSize,
            };
        }
Exemple #23
0
        public void Configure(IApplicationBuilder app)
        {
            app.Use(async(context, next) =>
            {
                if (!IsMultipartContentType(context.Request.ContentType))
                {
                    await next();
                    return;
                }

                var boundary = GetBoundary(context.Request.ContentType);
                var reader   = new MultipartReader(boundary, context.Request.Body);
                var section  = await reader.ReadNextSectionAsync();

                while (section != null)
                {
                    // process each image
                    const int chunkSize = 1024;
                    var buffer          = new byte[chunkSize];
                    var bytesRead       = 0;
                    var fileName        = GetFileName(section.ContentDisposition);

                    using (var stream = new FileStream(fileName, FileMode.Append))
                    {
                        do
                        {
                            bytesRead = await section.Body.ReadAsync(buffer, 0, buffer.Length);
                            stream.Write(buffer, 0, bytesRead);
                        } while (bytesRead > 0);
                    }

                    section = await reader.ReadNextSectionAsync();
                }

                context.Response.WriteAsync("Done.");
            });

            app.Run(async context =>
            {
                context.Response.ContentType = "text/html";
                await context.Response.WriteAsync("<html><body>");

                await context.Response.WriteAsync(@"
<FORM action = ""/"" method=""post"" enctype=""multipart/form-data"" >
<LABEL for=""myfile1"">File 1:</LABEL>
<INPUT type=""file"" name=""myfile1"" /><BR>
<LABEL for=""myfile2"">File 2:</LABEL>
<INPUT type=""file"" name=""myfile2"" /><BR>
<INPUT type=""submit"" value=""Send"" />
</FORM>");

                await context.Response.WriteAsync("</body></html>");
            });
        }
        public async Task <IActionResult> UploadAsync()
        {
            if (!IsMultipartContentType(Request.ContentType))
            {
                return(BadRequest($"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 filesUploaded = new List <string>();

            while (section != null)
            {
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);

                if (hasContentDispositionHeader)
                {
                    if (HasFileContentDisposition(contentDisposition))
                    {
                        logger.LogInformation($"The file name of uploaded file is: {contentDisposition.FileName}");
                        await storageRepository.SaveDocument($"{Guid.NewGuid()}_{contentDisposition.FileName}", section.Body);
                    }
                }
                else if (HasFormDataContentDisposition(contentDisposition))
                {
                    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);

                        if (formAccumulator.ValueCount > defaultFormOptions.ValueCountLimit)
                        {
                            throw new InvalidDataException($"Form key count limit {defaultFormOptions.ValueCountLimit} exceeded");
                        }
                    }
                }

                section = await reader.ReadNextSectionAsync();
            }

            return(Ok(new { Message = "File upload successful", Path = filesUploaded }));
        }
Exemple #25
0
        public static async System.Threading.Tasks.Task <ICollection <DigitalAsset> > Upload(IHttpContextAccessor httpContextAccessor, IAppDbContext context, CancellationToken cancellationToken)
        {
            var httpContext        = httpContextAccessor.HttpContext;
            var defaultFormOptions = new FormOptions();
            var digitalAssets      = new List <DigitalAsset>();

            if (!MultipartRequestHelper.IsMultipartContentType(httpContext.Request.ContentType))
            {
                throw new Exception($"Expected a multipart request, but got {httpContext.Request.ContentType}");
            }

            var mediaTypeHeaderValue = MediaTypeHeaderValue.Parse(httpContext.Request.ContentType);

            var boundary = MultipartRequestHelper.GetBoundary(
                mediaTypeHeaderValue,
                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 ContentDispositionHeaderValue contentDisposition);

                if (hasContentDispositionHeader)
                {
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        using (var targetStream = new MemoryStream())
                        {
                            await section.Body.CopyToAsync(targetStream, cancellationToken);

                            var name        = $"{contentDisposition.FileName}".Trim(new char[] { '"' }).Replace("&", "and");
                            var bytes       = StreamHelper.ReadToEnd(targetStream);
                            var contentType = section.ContentType;

                            var digitalAsset = new DigitalAsset(name, bytes, contentType);

                            context.Store(digitalAsset);

                            digitalAssets.Add(digitalAsset);
                        }
                    }
                }

                section = await reader.ReadNextSectionAsync(cancellationToken);
            }

            await context.SaveChangesAsync(cancellationToken);

            return(digitalAssets);
        }
Exemple #26
0
        private async Task Upload(HttpContext context, string cmd, UserItem userItem)
        {
            try
            {
                var boundary = context.Request.GetMultipartBoundary();

                if (string.IsNullOrWhiteSpace(boundary))
                {
                    await context.Response.WriteAsync(GetError(Api2Error.WrongRequest));

                    return;
                }

                string type = context.Request.Query["type"];
                string item = context.Request.Query["item"];

                // check type
                //Upload(string fileName, string description, Stream stream, string options)

                if (!DBManager.Instance.Get(type, out IManager manager))
                {
                    await context.Response.WriteAsync(GetError(Api2Error.Parameters));

                    return;
                }

                var reader  = new MultipartReader(boundary, context.Request.Body);
                var section = await reader.ReadNextSectionAsync();

                if (section == null)
                {
                    await context.Response.WriteAsync(GetError(Api2Error.Parameters));

                    return;
                }

                var fileSection = section.AsFileSection();
                var fileName    = fileSection.FileName;

                int id = await manager.Upload(userItem, fileSection.FileName, fileSection.FileStream, item);


                var result = new Api2Result(cmd);
                result["id"] = id;

                await context.Response.WriteAsync(JsonConvert.SerializeObject(result));
            }
            catch (Exception exc)
            {
                Logger.Instance.Save(exc);
                await context.Response.WriteAsync(GetError(Api2Error.Internal));
            }
        }
Exemple #27
0
    public async Task MultipartReader_HeadersLengthExceeded_Throws()
    {
        var stream = MakeStream(OnePartBodyTwoHeaders);
        var reader = new MultipartReader(Boundary, stream)
        {
            HeadersLengthLimit = 60,
        };

        var exception = await Assert.ThrowsAsync <InvalidDataException>(() => reader.ReadNextSectionAsync());

        Assert.Equal("Line length limit 17 exceeded.", exception.Message);
    }
Exemple #28
0
        public async Task <string> UploadImage()
        {
            var re     = Request;
            var apiKey = re.Headers.FirstOrDefault(x => x.Key.ToLower() == "x-api-key").Value;

            if (apiKey.ToString() != _realKey)
            {
                throw new ArgumentException("Invalid or no API Key provided (x-api-key header)");
            }

            var boundary = Request.GetMultipartBoundary();

            var reader  = new MultipartReader(boundary, Request.Body);
            var section = await reader.ReadNextSectionAsync();

            var disposition = section.GetContentDispositionHeader();

            if (disposition != null)
            {
                var fileSection = section.AsFileSection();

                var contentType = section.ContentType;

                // Generate random filename
                string hash;
                using (var md5 = MD5.Create())
                {
                    hash = BitConverter.ToString(md5.ComputeHash(Encoding.ASCII.GetBytes(fileSection.FileName))).Replace("-", "").ToLower();
                }

                var timestamp = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds().ToString();
                var filename  = _generateFilename(disposition.FileName.ToString());
                filename += timestamp.Substring(timestamp.Length - 2);
                filename += hash.Substring(0, 2);
                var extension = MimeTypesMap.GetExtension(contentType);
                filename += $".{extension}";


                string path = Path.Combine(_storagePath, $"{filename}");
                using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write))
                {
                    fileSection.FileStream.Position = 0;
                    await fileSection.FileStream.CopyToAsync(fileStream);
                }


                return($"{_url}/{filename}");
            }
            else
            {
                throw new ArgumentException("No Content-Disposition header");
            }
        }
Exemple #29
0
        public void MultipartReader_HeaderCountExceeded_Throws()
        {
            var stream = MakeStream(OnePartBodyTwoHeaders);
            var reader = new MultipartReader(Boundary, stream)
            {
                HeadersCountLimit = 1,
            };

            var exception = Assert.ThrowsAsync <InvalidDataException>(async() => await reader.ReadNextSectionAsync());

            Assert.That(exception.Message, Is.EqualTo("Multipart headers count limit 1 exceeded."));
        }
        public async Task <string> ValidateImportRequestData(HttpRequest request)
        {
            FormOptions _defaultFormOptions = new FormOptions();
            var         accumulator         = new KeyValueAccumulator();
            string      filePath            = Path.GetTempFileName();

            var boundary = MultipartRequest.GetBoundary(MediaTypeHeaderValue.Parse(request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader   = new MultipartReader(boundary, request.Body);
            var section  = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out ContentDispositionHeaderValue contentDisposition);

                if (hasContentDispositionHeader)
                {
                    if (MultipartRequest.HasFileContentDisposition(contentDisposition))
                    {
                        using (var targetStream = File.Create(filePath))
                        {
                            await section.Body.CopyToAsync(targetStream);
                        }
                    }
                    else if (MultipartRequest.HasFormDataContentDisposition(contentDisposition))
                    {
                        var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name).ToString();
                        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;
                            }
                            accumulator.Append(key, value);

                            if (accumulator.ValueCount > _defaultFormOptions.ValueCountLimit)
                            {
                                throw new InvalidDataException($"For key count limit {_defaultFormOptions.ValueCountLimit} exceeded");
                            }
                        }
                    }
                }
                section = await reader.ReadNextSectionAsync();
            }
            return(filePath);
        }
        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 MutipartReader_HeadersLengthExceeded_Throws()
        {
            var stream = MakeStream(OnePartBodyTwoHeaders);
            var reader = new MultipartReader(Boundary, stream)
            {
                HeadersLengthLimit = 60,
            };

            var exception = await Assert.ThrowsAsync<InvalidDataException>(() => reader.ReadNextSectionAsync());
            Assert.Equal("Line length limit 17 exceeded.", exception.Message);
        }
        public async Task MutipartReader_ReadSinglePartBodyWithoutLastCRLF_Success()
        {
            var stream = MakeStream(OnePartBodyWithoutFinalCRLF);
            var reader = new MultipartReader(Boundary, stream);

            var section = await reader.ReadNextSectionAsync();
            Assert.NotNull(section);
            Assert.Equal(1, section.Headers.Count);
            Assert.Equal("form-data; name=\"text\"", section.Headers["Content-Disposition"][0]);
            var buffer = new MemoryStream();
            await section.Body.CopyToAsync(buffer);
            Assert.Equal("text default", Encoding.ASCII.GetString(buffer.ToArray()));

            Assert.Null(await reader.ReadNextSectionAsync());
        }
 public void MutipartReader_BufferSizeMustBeLargerThanBoundary_Throws()
 {
     var stream = MakeStream(ThreePartBody);
     Assert.Throws<ArgumentOutOfRangeException>(() =>
     {
         var reader = new MultipartReader(Boundary, stream, 5);
     });
 }
        public async Task MutipartReader_TwoPartBodyIncompleteBuffer_TwoSectionsReadSuccessfullyThirdSectionThrows()
        {
            var stream = MakeStream(TwoPartBodyIncompleteBuffer);
            var reader = new MultipartReader(Boundary, stream);
            var buffer = new byte[128];

            //first section can be read successfully
            var section = await reader.ReadNextSectionAsync();
            Assert.NotNull(section);
            Assert.Equal(1, section.Headers.Count);
            Assert.Equal("form-data; name=\"text\"", section.Headers["Content-Disposition"][0]);
            var read = section.Body.Read(buffer, 0, buffer.Length);
            Assert.Equal("text default", GetString(buffer, read));

            //second section can be read successfully (even though the bottom boundary is truncated)
            section = await reader.ReadNextSectionAsync();
            Assert.NotNull(section);
            Assert.Equal(2, section.Headers.Count);
            Assert.Equal("form-data; name=\"file1\"; filename=\"a.txt\"", section.Headers["Content-Disposition"][0]);
            Assert.Equal("text/plain", section.Headers["Content-Type"][0]);
            read = section.Body.Read(buffer, 0, buffer.Length);
            Assert.Equal("Content of a.txt.\r\n", GetString(buffer, read));

            await Assert.ThrowsAsync<IOException>(async () =>
            {
                // we'll be unable to ensure enough bytes are buffered to even contain a final boundary
                section = await reader.ReadNextSectionAsync();
            });
        }
        public async Task MutipartReader_ReadTwoPartBodyWithUnicodeFileName_Success()
        {
            var stream = MakeStream(TwoPartBodyWithUnicodeFileName);
            var reader = new MultipartReader(Boundary, stream);

            var section = await reader.ReadNextSectionAsync();
            Assert.NotNull(section);
            Assert.Equal(1, section.Headers.Count);
            Assert.Equal("form-data; name=\"text\"", section.Headers["Content-Disposition"][0]);
            var buffer = new MemoryStream();
            await section.Body.CopyToAsync(buffer);
            Assert.Equal("text default", Encoding.ASCII.GetString(buffer.ToArray()));

            section = await reader.ReadNextSectionAsync();
            Assert.NotNull(section);
            Assert.Equal(2, section.Headers.Count);
            Assert.Equal("form-data; name=\"file1\"; filename=\"a色.txt\"", section.Headers["Content-Disposition"][0]);
            Assert.Equal("text/plain", section.Headers["Content-Type"][0]);
            buffer = new MemoryStream();
            await section.Body.CopyToAsync(buffer);
            Assert.Equal("Content of a.txt.\r\n", Encoding.ASCII.GetString(buffer.ToArray()));

            Assert.Null(await reader.ReadNextSectionAsync());
        }
        public async Task MutipartReader_ThreePartBody_Success()
        {
            var stream = MakeStream(ThreePartBody);
            var reader = new MultipartReader(Boundary, stream);

            var section = await reader.ReadNextSectionAsync();
            Assert.NotNull(section);
            Assert.Equal(1, section.Headers.Count);
            Assert.Equal("form-data; name=\"text\"", section.Headers["Content-Disposition"][0]);
            var buffer = new MemoryStream();
            await section.Body.CopyToAsync(buffer);
            Assert.Equal("text default", Encoding.ASCII.GetString(buffer.ToArray()));

            section = await reader.ReadNextSectionAsync();
            Assert.NotNull(section);
            Assert.Equal(2, section.Headers.Count);
            Assert.Equal("form-data; name=\"file1\"; filename=\"a.txt\"", section.Headers["Content-Disposition"][0]);
            Assert.Equal("text/plain", section.Headers["Content-Type"][0]);
            buffer = new MemoryStream();
            await section.Body.CopyToAsync(buffer);
            Assert.Equal("Content of a.txt.\r\n", Encoding.ASCII.GetString(buffer.ToArray()));

            section = await reader.ReadNextSectionAsync();
            Assert.NotNull(section);
            Assert.Equal(2, section.Headers.Count);
            Assert.Equal("form-data; name=\"file2\"; filename=\"a.html\"", section.Headers["Content-Disposition"][0]);
            Assert.Equal("text/html", section.Headers["Content-Type"][0]);
            buffer = new MemoryStream();
            await section.Body.CopyToAsync(buffer);
            Assert.Equal("<!DOCTYPE html><title>Content of a.html.</title>\r\n", Encoding.ASCII.GetString(buffer.ToArray()));

            Assert.Null(await reader.ReadNextSectionAsync());
        }
        public async Task MutipartReader_ReadInvalidUtf8SurrogateHeader_ReplacementCharacters()
        {
            var body1 =
"--9051914041544843365972754266\r\n" +
"Content-Disposition: form-data; name=\"text\" filename=\"a";

            var body2 =
".txt\"\r\n" +
"\r\n" +
"text default\r\n" +
"--9051914041544843365972754266--\r\n";
            var stream = new MemoryStream();
            var bytes = Encoding.UTF8.GetBytes(body1);
            stream.Write(bytes, 0, bytes.Length);

            // Write an invalid utf-8 segment in the middle
            stream.Write(new byte[] { 0xED, 0xA0, 85 }, 0, 3);

            bytes = Encoding.UTF8.GetBytes(body2);
            stream.Write(bytes, 0, bytes.Length);
            stream.Seek(0, SeekOrigin.Begin);
            var reader = new MultipartReader(Boundary, stream);

            var section = await reader.ReadNextSectionAsync();
            Assert.NotNull(section);
            Assert.Equal(1, section.Headers.Count);
            Assert.Equal("form-data; name=\"text\" filename=\"a\uFFFDU.txt\"", section.Headers["Content-Disposition"][0]);
            var buffer = new MemoryStream();
            await section.Body.CopyToAsync(buffer);
            Assert.Equal("text default", Encoding.ASCII.GetString(buffer.ToArray()));

            Assert.Null(await reader.ReadNextSectionAsync());
        }