Skip to content

Commit cf7dfc7

Browse files
committed
Properly close channel in SynchronossPart
This commit properly closes the opened channels in the SynchronossPart, and also makes sure that the entire contents is copied, not just the first batch.
1 parent 2705788 commit cf7dfc7

File tree

2 files changed

+33
-9
lines changed

2 files changed

+33
-9
lines changed

spring-web/src/main/java/org/springframework/http/codec/multipart/Part.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,10 @@ public interface Part {
7373

7474
/**
7575
* Transfer the file in this part to the given file destination.
76-
* @param dest the target file
76+
* @param destination the target file
7777
* @return completion {@code Mono} with the result of the file transfer,
7878
* possibly {@link IllegalStateException} if the part isn't a file
7979
*/
80-
Mono<Void> transferTo(File dest);
80+
Mono<Void> transferTo(File destination);
8181

8282
}

spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossMultipartHttpMessageReader.java

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
*
6767
* @author Sebastien Deleuze
6868
* @author Rossen Stoyanchev
69+
* @author Arjen Poutsma
6970
* @since 5.0
7071
* @see <a href="https://github.com/synchronoss/nio-multipart">Synchronoss NIO Multipart</a>
7172
*/
@@ -301,22 +302,45 @@ public Flux<DataBuffer> getContent() {
301302
}
302303

303304
@Override
304-
public Mono<Void> transferTo(File dest) {
305+
public Mono<Void> transferTo(File destination) {
305306
if (this.storage == null || !getFilename().isPresent()) {
306307
return Mono.error(new IllegalStateException("The part does not represent a file."));
307308
}
309+
ReadableByteChannel input = null;
310+
FileChannel output = null;
308311
try {
309-
ReadableByteChannel ch = Channels.newChannel(this.storage.getInputStream());
310-
long expected = (ch instanceof FileChannel ? ((FileChannel) ch).size() : Long.MAX_VALUE);
311-
long actual = new FileOutputStream(dest).getChannel().transferFrom(ch, 0, expected);
312-
if (actual < expected) {
313-
return Mono.error(new IOException(
314-
"Could only write " + actual + " out of " + expected + " bytes"));
312+
input = Channels.newChannel(this.storage.getInputStream());
313+
output = new FileOutputStream(destination).getChannel();
314+
315+
long size = (input instanceof FileChannel ? ((FileChannel) input).size() : Long.MAX_VALUE);
316+
long totalWritten = 0;
317+
while (totalWritten < size) {
318+
long written = output.transferFrom(input, totalWritten, size - totalWritten);
319+
if (written <= 0) {
320+
break;
321+
}
322+
totalWritten += written;
315323
}
316324
}
317325
catch (IOException ex) {
318326
return Mono.error(ex);
319327
}
328+
finally {
329+
if (input != null) {
330+
try {
331+
input.close();
332+
}
333+
catch (IOException ignored) {
334+
}
335+
}
336+
if (output != null) {
337+
try {
338+
output.close();
339+
}
340+
catch (IOException ignored) {
341+
}
342+
}
343+
}
320344
return Mono.empty();
321345
}
322346
}

0 commit comments

Comments
 (0)