Reputation: 460
I need to download files (currently images) from an FTP server by a Java client, and return it to a web application.
The problem is: A few kilobytes (maybe 64KB) of the image is downloaded, but the rest is missing, so only the upper part of the image is displayed on the UI. No exceptions, no errors in the logs - simply it looks like my machine is lazy.
When suggesting solutions, please keep in mind this function will be used for downloading large files (with size bigger than the available memory or disk space), so I need to forward the data to the client without actually reading it at once.
My code:
FTP client:
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import java.io.IOException;
import java.io.InputStream;
@Slf4j
public class FtpClientWrapper implements AutoCloseable {
private final FTPClient client;
@SneakyThrows
public FtpClientWrapper(FtpClientProperties properties) {
FTPClient client = new FTPClient();
client.connect(properties.getServer(), properties.getPort());
client.enterLocalPassiveMode();
int reply = client.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
client.disconnect();
throw new IOException("Exception in connecting to FTP Server. ReplyCode: " + reply);
}
boolean loginSuccess = client.login(properties.getUsername(), properties.getPassword());
if (!loginSuccess) {
throw new RuntimeException("FTP login failed.");
}
this.client = client;
}
@SneakyThrows
public InputStream downloadFile(String fileName) {
client.setFileType(FTP.BINARY_FILE_TYPE);
return client.retrieveFileStream(fileName);
}
}
Controller method:
@Override
public ResponseEntity<InputStreamResource> downloadFile(String fileName) {
InputStream result = ftpClient.downloadFile(fileName);
return ResponseEntity.ok()
.contentLength(<correct file size>)
.contentType(<proper content type>)
.body(new InputStreamResource(result));
}
And the result:
Upvotes: 0
Views: 435
Reputation: 460
Problem solved - It is not a good idea closing the FtpClient before the InputStream is read.
Upvotes: 0