@Override public Flux<DataBuffer> getBody() { return this.part.content(); } }
@Override public HttpHeaders getHeaders() { return this.part.headers(); }
assertEquals("name 1", part.name()); assertEquals("value 1", ((FormFieldPart) part).value()); part = parts2.get(0); assertTrue(part instanceof FormFieldPart); assertEquals("name 2", part.name()); assertEquals("value 2+1", ((FormFieldPart) part).value()); part = parts2.get(1); assertTrue(part instanceof FormFieldPart); assertEquals("name 2", part.name()); assertEquals("value 2+2", ((FormFieldPart) part).value()); assertEquals("logo", part.name()); assertEquals("logo.jpg", ((FilePart) part).filename()); assertEquals(MediaType.IMAGE_JPEG, part.headers().getContentType()); assertEquals(logo.getFile().length(), part.headers().getContentLength()); assertEquals("utf8", part.name()); assertEquals("Hall\u00F6le.jpg", ((FilePart) part).filename()); assertEquals(MediaType.IMAGE_JPEG, part.headers().getContentType()); assertEquals(utf8.getFile().length(), part.headers().getContentLength()); assertEquals("json", part.name()); assertEquals(MediaType.APPLICATION_JSON_UTF8, part.headers().getContentType()); String value = StringDecoder.textPlainOnly(false).decodeToMono(part.content(), ResolvableType.forClass(String.class), MediaType.TEXT_PLAIN, Collections.emptyMap()).block(Duration.ZERO);
@Test // SPR-16402 public void singleSubscriberWithResource() throws IOException { UnicastProcessor<Resource> processor = UnicastProcessor.create(); Resource logo = new ClassPathResource("/org/springframework/http/converter/logo.jpg"); Mono.just(logo).subscribe(processor); MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder(); bodyBuilder.asyncPart("logo", processor, Resource.class); Mono<MultiValueMap<String, HttpEntity<?>>> result = Mono.just(bodyBuilder.build()); Map<String, Object> hints = Collections.emptyMap(); this.writer.write(result, null, MediaType.MULTIPART_FORM_DATA, this.response, hints).block(); MultiValueMap<String, Part> requestParts = parse(hints); assertEquals(1, requestParts.size()); Part part = requestParts.getFirst("logo"); assertEquals("logo", part.name()); assertTrue(part instanceof FilePart); assertEquals("logo.jpg", ((FilePart) part).filename()); assertEquals(MediaType.IMAGE_JPEG, part.headers().getContentType()); assertEquals(logo.getFile().length(), part.headers().getContentLength()); }
private void assertFooPart(Part part) { assertEquals("fooPart", part.name()); assertTrue(part instanceof FilePart); assertEquals("foo.txt", ((FilePart) part).filename()); StepVerifier.create(DataBufferUtils.join(part.content())) .consumeNextWith(buffer -> { assertEquals(12, buffer.readableByteCount()); byte[] byteContent = new byte[12]; buffer.read(byteContent); assertEquals("Lorem Ipsum.", new String(byteContent)); }) .verifyComplete(); }
@RequestMapping(value = "/post", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public Mono<Map<String, Object>> postFormData(@RequestBody Mono<MultiValueMap<String, Part>> parts) { // StringDecoder decoder = StringDecoder.allMimeTypes(true); return parts.flux().flatMap(map -> Flux.fromIterable(map.values())) .flatMap(Flux::fromIterable) .filter(part -> part instanceof FilePart) .reduce(new HashMap<String, Object>(), (files, part) -> { MediaType contentType = part.headers().getContentType(); long contentLength = part.headers().getContentLength(); files.put(part.name(), "data:"+contentType+";base64,"+contentLength); //TODO: get part data return files; }).map(files -> Collections.singletonMap("files", files)); }
@Test public void resolveParts() { ServerHttpRequest request = generateMultipartRequest(); ResolvableType elementType = forClassWithGenerics(MultiValueMap.class, String.class, Part.class); MultiValueMap<String, Part> parts = this.reader.readMono(elementType, request, emptyMap()).block(); assertEquals(2, parts.size()); assertTrue(parts.containsKey("fooPart")); Part part = parts.getFirst("fooPart"); assertTrue(part instanceof FilePart); assertEquals("fooPart", part.name()); assertEquals("foo.txt", ((FilePart) part).filename()); DataBuffer buffer = DataBufferUtils.join(part.content()).block(); assertEquals(12, buffer.readableByteCount()); byte[] byteContent = new byte[12]; buffer.read(byteContent); assertEquals("Lorem Ipsum.", new String(byteContent)); assertTrue(parts.containsKey("barPart")); part = parts.getFirst("barPart"); assertTrue(part instanceof FormFieldPart); assertEquals("barPart", part.name()); assertEquals("bar", ((FormFieldPart) part).value()); }
private Flux<?> decodePartValues(Flux<Part> parts, MethodParameter elementType, BindingContext bindingContext, ServerWebExchange exchange, boolean isRequired) { return parts.flatMap(part -> { ServerHttpRequest partRequest = new PartServerHttpRequest(exchange.getRequest(), part); ServerWebExchange partExchange = exchange.mutate().request(partRequest).build(); if (logger.isDebugEnabled()) { logger.debug(exchange.getLogPrefix() + "Decoding part '" + part.name() + "'"); } return readBody(elementType, isRequired, bindingContext, partExchange); }); }
private String partToUtf8String(Part part) { DataBuffer buffer = DataBufferUtils.join(part.content()).block(); return DataBufferTestUtils.dumpString(buffer, StandardCharsets.UTF_8); }
@Test // SPR-16376 public void customContentDisposition() throws IOException { Resource logo = new ClassPathResource("/org/springframework/http/converter/logo.jpg"); Flux<DataBuffer> buffers = DataBufferUtils.read(logo, new DefaultDataBufferFactory(), 1024); long contentLength = logo.contentLength(); MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder(); bodyBuilder.part("resource", logo) .headers(h -> h.setContentDispositionFormData("resource", "spring.jpg")); bodyBuilder.asyncPart("buffers", buffers, DataBuffer.class) .headers(h -> { h.setContentDispositionFormData("buffers", "buffers.jpg"); h.setContentType(MediaType.IMAGE_JPEG); h.setContentLength(contentLength); }); MultiValueMap<String, HttpEntity<?>> multipartData = bodyBuilder.build(); Map<String, Object> hints = Collections.emptyMap(); this.writer.write(Mono.just(multipartData), null, MediaType.MULTIPART_FORM_DATA, this.response, hints).block(); MultiValueMap<String, Part> requestParts = parse(hints); assertEquals(2, requestParts.size()); Part part = requestParts.getFirst("resource"); assertTrue(part instanceof FilePart); assertEquals("spring.jpg", ((FilePart) part).filename()); assertEquals(logo.getFile().length(), part.headers().getContentLength()); part = requestParts.getFirst("buffers"); assertTrue(part instanceof FilePart); assertEquals("buffers.jpg", ((FilePart) part).filename()); assertEquals(logo.getFile().length(), part.headers().getContentLength()); }
@Override public Flux<Part> read(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints) { return Flux.create(new SynchronossPartGenerator(message, this.bufferFactory, this.streamStorageFactory)) .doOnNext(part -> { if (!Hints.isLoggingSuppressed(hints)) { LogFormatUtils.traceDebug(logger, traceOn -> Hints.getLogPrefix(hints) + "Parsed " + (isEnableLoggingRequestDetails() ? LogFormatUtils.formatValue(part, !traceOn) : "parts '" + part.name() + "' (content masked)")); } }); }
@Test public void part() { MethodParameter param = this.testMethod.annot(requestPart()).arg(Part.class); MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder(); bodyBuilder.part("name", new Person("Jones")); Part actual = resolveArgument(param, bodyBuilder); DataBuffer buffer = DataBufferUtils.join(actual.content()).block(); assertEquals("{\"name\":\"Jones\"}", DataBufferTestUtils.dumpString(buffer, StandardCharsets.UTF_8)); }
private void assertBarPart(Part part) { assertEquals("barPart", part.name()); assertTrue(part instanceof FormFieldPart); assertEquals("bar", ((FormFieldPart) part).value()); } }
private ByteArrayOutputStream readPartBodyContent(Part part) { ByteArrayOutputStream contentStream = new ByteArrayOutputStream(); DataBufferUtils.write(part.content(), contentStream).blockFirst(); return contentStream; }
@Override public Flux<Part> read(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints) { return Flux.create(new SynchronossPartGenerator(message, this.bufferFactory, this.streamStorageFactory)) .doOnNext(part -> { if (!Hints.isLoggingSuppressed(hints)) { LogFormatUtils.traceDebug(logger, traceOn -> Hints.getLogPrefix(hints) + "Parsed " + (isEnableLoggingRequestDetails() ? LogFormatUtils.formatValue(part, !traceOn) : "parts '" + part.name() + "' (content masked)")); } }); }
assertEquals("text", part.name()); assertTrue(part instanceof FormFieldPart); FormFieldPart formFieldPart = (FormFieldPart) part; }) .consumeNextWith(part -> { assertEquals("file1", part.name()); assertTrue(part instanceof FilePart); FilePart filePart = (FilePart) part; }) .consumeNextWith(part -> { assertEquals("file2", part.name()); assertTrue(part instanceof FilePart); FilePart filePart = (FilePart) part;
@Override public Flux<Part> read(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints) { return Flux.create(new SynchronossPartGenerator(message, this.bufferFactory, this.streamStorageFactory)) .doOnNext(part -> { if (!Hints.isLoggingSuppressed(hints)) { LogFormatUtils.traceDebug(logger, traceOn -> Hints.getLogPrefix(hints) + "Parsed " + (isEnableLoggingRequestDetails() ? LogFormatUtils.formatValue(part, !traceOn) : "parts '" + part.name() + "' (content masked)")); } }); }