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.
This commit is contained in:
Arjen Poutsma 2017-05-03 14:44:48 +02:00
parent 27057889f8
commit cf7dfc7b17
2 changed files with 33 additions and 9 deletions

View File

@ -73,10 +73,10 @@ public interface Part {
/** /**
* Transfer the file in this part to the given file destination. * 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, * @return completion {@code Mono} with the result of the file transfer,
* possibly {@link IllegalStateException} if the part isn't a file * possibly {@link IllegalStateException} if the part isn't a file
*/ */
Mono<Void> transferTo(File dest); Mono<Void> transferTo(File destination);
} }

View File

@ -66,6 +66,7 @@ import org.springframework.util.StreamUtils;
* *
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Arjen Poutsma
* @since 5.0 * @since 5.0
* @see <a href="https://github.com/synchronoss/nio-multipart">Synchronoss NIO Multipart</a> * @see <a href="https://github.com/synchronoss/nio-multipart">Synchronoss NIO Multipart</a>
*/ */
@ -301,22 +302,45 @@ public class SynchronossMultipartHttpMessageReader implements HttpMessageReader<
} }
@Override @Override
public Mono<Void> transferTo(File dest) { public Mono<Void> transferTo(File destination) {
if (this.storage == null || !getFilename().isPresent()) { if (this.storage == null || !getFilename().isPresent()) {
return Mono.error(new IllegalStateException("The part does not represent a file.")); return Mono.error(new IllegalStateException("The part does not represent a file."));
} }
ReadableByteChannel input = null;
FileChannel output = null;
try { try {
ReadableByteChannel ch = Channels.newChannel(this.storage.getInputStream()); input = Channels.newChannel(this.storage.getInputStream());
long expected = (ch instanceof FileChannel ? ((FileChannel) ch).size() : Long.MAX_VALUE); output = new FileOutputStream(destination).getChannel();
long actual = new FileOutputStream(dest).getChannel().transferFrom(ch, 0, expected);
if (actual < expected) { long size = (input instanceof FileChannel ? ((FileChannel) input).size() : Long.MAX_VALUE);
return Mono.error(new IOException( long totalWritten = 0;
"Could only write " + actual + " out of " + expected + " bytes")); while (totalWritten < size) {
long written = output.transferFrom(input, totalWritten, size - totalWritten);
if (written <= 0) {
break;
}
totalWritten += written;
} }
} }
catch (IOException ex) { catch (IOException ex) {
return Mono.error(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(); return Mono.empty();
} }
} }