简体   繁体   中英

Java FTP client does not download the whole file

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:

在此处输入图像描述

Problem solved - It is not a good idea closing the FtpClient before the InputStream is read.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM