diff --git a/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReader.java b/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReader.java index 30dce891b49..ad04d9a43d4 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReader.java +++ b/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReader.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,11 +17,13 @@ package org.springframework.http.codec.multipart; import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.StandardOpenOption; @@ -82,6 +84,8 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem // Static DataBufferFactory to copy from FileInputStream or wrap bytes[]. private static final DataBufferFactory bufferFactory = new DefaultDataBufferFactory(); + private static final String FILE_STORAGE_DIRECTORY_PREFIX = "synchronoss-file-upload-"; + private int maxInMemorySize = 256 * 1024; @@ -89,6 +93,8 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem private int maxParts = -1; + private Path fileStorageDirectory = createTempDirectory(); + /** * Configure the maximum amount of memory that is allowed to use per part. @@ -172,7 +178,7 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem @Override public Flux read(ResolvableType elementType, ReactiveHttpInputMessage message, Map hints) { - return Flux.create(new SynchronossPartGenerator(message)) + return Flux.create(new SynchronossPartGenerator(message, this.fileStorageDirectory)) .doOnNext(part -> { if (!Hints.isLoggingSuppressed(hints)) { LogFormatUtils.traceDebug(logger, traceOn -> Hints.getLogPrefix(hints) + "Parsed " + @@ -188,6 +194,15 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem return Mono.error(new UnsupportedOperationException("Cannot read multipart request body into single Part")); } + private static Path createTempDirectory() { + try { + return Files.createTempDirectory(FILE_STORAGE_DIRECTORY_PREFIX); + } + catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + /** * Subscribe to the input stream and feed the Synchronoss parser. Then listen @@ -199,14 +214,17 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem private final LimitedPartBodyStreamStorageFactory storageFactory = new LimitedPartBodyStreamStorageFactory(); + private final Path fileStorageDirectory; + @Nullable private NioMultipartParserListener listener; @Nullable private NioMultipartParser parser; - public SynchronossPartGenerator(ReactiveHttpInputMessage inputMessage) { + public SynchronossPartGenerator(ReactiveHttpInputMessage inputMessage, Path fileStorageDirectory) { this.inputMessage = inputMessage; + this.fileStorageDirectory = fileStorageDirectory; } @Override @@ -223,6 +241,7 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem this.parser = Multipart .multipart(context) + .saveTemporaryFilesTo(this.fileStorageDirectory.toString()) .usePartBodyStreamStorageFactory(this.storageFactory) .forNIO(this.listener);