public static async Task<IMultipartCollection> ReadMultipartAsync(this HttpRequest request, CancellationToken cancellationToken) {
            cancellationToken.ThrowIfCancellationRequested();

            request.EnableRewind();

            var parts = new MultipartCollection();

            using(cancellationToken.Register(request.HttpContext.Abort)) {
                var contentType = GetContentType(request);
                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);
                    var contentDisposition = headers.GetContentDisposition();

                    await section.Body.DrainAsync(cancellationToken);

                    var part = new Multipart(request.Body, section.BaseStreamOffset.Value, section.Body.Length) {
                        Headers = headers
                    };
                    parts.Add(part);

                    section = await multipartReader.ReadNextSectionAsync(cancellationToken);
                }

            }

            request.Body.Seek(0, SeekOrigin.Begin);

            return parts;
        }
        public async Task MutipartReader_ReadSinglePartBody_Success()
        {
            var stream = MakeStream(OnePartBody);
            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());
        }
Ejemplo n.º 3
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            app.UseIISPlatformHandler();

            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.Body.WriteAsync("Done.");
            });

            app.UseStaticFiles();

            app.UseMvc();
        }
        public async Task MutipartReader_ReadSinglePartBody_Success()
        {
            var stream = MakeStream(OnePartBody);
            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 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());
        }
Ejemplo n.º 7
0
        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;
        }
Ejemplo n.º 8
0
        public void Configure(IApplicationBuilder app)
        {
            app.Use(async (context, next) =>
            {
                if (!IsMultipartContentType(context.Request.ContentType))
                {
                    await next();
                    return;
                }

                context.Response.ContentType = "text/html";
                await context.Response.WriteAsync("<html><body>Multipart received<br>");

                // Read the request body as multipart sections. This does not buffer the content of each section. If you want to buffer the data
                // then that needs to be added either to the request body before you start or to the individual segments afterward.
                var boundary = GetBoundary(context.Request.ContentType);
                var reader = new MultipartReader(boundary, context.Request.Body);

                var section = await reader.ReadNextSectionAsync();
                while (section != null)
                {
                    await context.Response.WriteAsync("- Header count: " + section.Headers.Count + "<br>");
                    foreach (var headerPair in section.Headers)
                    {
                        await context.Response.WriteAsync("-- " + headerPair.Key + ": " + string.Join(", ", headerPair.Value) + "<br>");
                    }

                    // Consume the section body here.

                    // Nested?
                    if (IsMultipartContentType(section.ContentType))
                    {
                        await context.Response.WriteAsync("-- Nested Multipart<br>");

                        var subBoundary = GetBoundary(section.ContentType);

                        var subReader = new MultipartReader(subBoundary, section.Body);

                        var subSection = await subReader.ReadNextSectionAsync();
                        while (subSection != null)
                        {
                            await context.Response.WriteAsync("--- Header count: " + subSection.Headers.Count + "<br>");
                            foreach (var headerPair in subSection.Headers)
                            {
                                await context.Response.WriteAsync("---- " + headerPair.Key + ": " + string.Join(", ", headerPair.Value) + "<br>");
                            }

                            subSection = await subReader.ReadNextSectionAsync();
                        }
                    }

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

                await context.Response.WriteAsync("</body></html>");
            });

            app.Use(async (context, next) =>
            {
                if (context.Request.Path != new PathString("/SendMultipart"))
                {
                    await next();
                    return;
                }

                // For the purposes of the sample we're going to issue a multipart request to ourselves and then tunnel the response to the user.
                var client = new HttpClient();
                client.BaseAddress = new Uri("http://localhost:" + context.GetFeature<IHttpConnectionFeature>().LocalPort);

                var content = new MultipartContent("stuff");
                content.Add(new StringContent("Hello World"));
                content.Add(new FormUrlEncodedContent(new Dictionary<string, string>()));
                content.Add(new MultipartContent("nested") { new StringContent("Nested Hello World") });

                var response = await client.PostAsync("", content);

                context.Response.StatusCode = (int)response.StatusCode;
                context.Response.ContentType = response.Content.Headers.ContentType.ToString();
                await response.Content.CopyToAsync(context.Response.Body);
            });

            app.Run(async context =>
            {
                context.Response.ContentType = "text/html";
                await context.Response.WriteAsync("<html><body>Normal request.<br>");
                await context.Response.WriteAsync("<a href=\"/SendMultipart\">Send Multipart Request</a><br>");
                await context.Response.WriteAsync("</body></html>");
            });
        }
Ejemplo n.º 9
0
        private async Task SaveFiles(IOwinContext context, Group boundary, List<UploadedFile> uploadedFiles)
        {
            // get the file store
            var fileStore = configuration.ServiceLocator.GetService<IUploadedFileStorage>();

            // parse the stream
            var multiPartReader = new MultipartReader(boundary.Value, context.Request.Body);
            MultipartSection section;
            while ((section = await multiPartReader.ReadNextSectionAsync()) != null)
            {
                // process the section
                var result = await StoreFile(section, fileStore);
                if (result != null)
                {
                    uploadedFiles.Add(result);
                }
            }
        }
        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());
        }
        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_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());
        }