diff --git a/spring-web/src/main/java/org/springframework/http/codec/multipart/Part.java b/spring-web/src/main/java/org/springframework/http/codec/multipart/Part.java index e8bcc15d98..b47bc02206 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/multipart/Part.java +++ b/spring-web/src/main/java/org/springframework/http/codec/multipart/Part.java @@ -73,10 +73,10 @@ public interface Part { /** * Transfer the file in this part to the given file destination. - * @param dest the target file + * @param destination the target file * @return completion {@code Mono} with the result of the file transfer, * possibly {@link IllegalStateException} if the part isn't a file */ - Mono transferTo(File dest); + Mono transferTo(File destination); } diff --git a/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossMultipartHttpMessageReader.java b/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossMultipartHttpMessageReader.java index 153574f86a..a94ebfcd01 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossMultipartHttpMessageReader.java +++ b/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossMultipartHttpMessageReader.java @@ -66,6 +66,7 @@ import org.springframework.util.StreamUtils; * * @author Sebastien Deleuze * @author Rossen Stoyanchev + * @author Arjen Poutsma * @since 5.0 * @see Synchronoss NIO Multipart */ @@ -301,22 +302,45 @@ public class SynchronossMultipartHttpMessageReader implements HttpMessageReader< } @Override - public Mono transferTo(File dest) { + public Mono transferTo(File destination) { if (this.storage == null || !getFilename().isPresent()) { return Mono.error(new IllegalStateException("The part does not represent a file.")); } + ReadableByteChannel input = null; + FileChannel output = null; try { - ReadableByteChannel ch = Channels.newChannel(this.storage.getInputStream()); - long expected = (ch instanceof FileChannel ? ((FileChannel) ch).size() : Long.MAX_VALUE); - long actual = new FileOutputStream(dest).getChannel().transferFrom(ch, 0, expected); - if (actual < expected) { - return Mono.error(new IOException( - "Could only write " + actual + " out of " + expected + " bytes")); + input = Channels.newChannel(this.storage.getInputStream()); + output = new FileOutputStream(destination).getChannel(); + + long size = (input instanceof FileChannel ? ((FileChannel) input).size() : Long.MAX_VALUE); + long totalWritten = 0; + while (totalWritten < size) { + long written = output.transferFrom(input, totalWritten, size - totalWritten); + if (written <= 0) { + break; + } + totalWritten += written; } } catch (IOException ex) { return Mono.error(ex); } + finally { + if (input != null) { + try { + input.close(); + } + catch (IOException ignored) { + } + } + if (output != null) { + try { + output.close(); + } + catch (IOException ignored) { + } + } + } return Mono.empty(); } }