Jordan Noel
Jordan Noel

Reputation: 239

Images downloaded from "some" servers with FTPClient are corrupted

I need to download .png files from a FTP server in Java. I have 3 different servers, each one contain a folder with exactly the same .png files.

On server 1 :
If I download my .png file of 4686 bytes stored on this server with FTPClient (apache.commons.net.ftp), I get a 4706 bytes .png file, and I can't open it. If I download it with Total Commander, I get a 4686 bytes .png file, and I can open it.

On server 2 and 3 :
With FTPClient and Total Commander, I get in both case a 4686 bytes file and I can open it without problem.

My code :

FTPClient ftpClient = new FTPClient();
ftpClient.connect("...", PORT);
ftpClient.login("...", "...");
ftpClient.enterLocalPassiveMode();
FTPFile[] imageFiles = ftpClient.listFiles(distantPathForImages);
for (FTPFile imageFile : imageFiles) {
    InputStream inputStream = ftpClient.retrieveFileStream(distantPathForImages + imageFile.getName());
    OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(new File(PATHDESTCSS + imageFile.getName())));
    byte[] bytesArray = new byte[65536];
    int bytesRead;
    while ((bytesRead = inputStream.read(bytesArray)) != -1) {
        outputStream.write(bytesArray, 0, bytesRead);
    }
    outputStream.close();
    inputStream.close();
    ftpClient.completePendingCommand();
}

Why does my file have these "extra bytes" only when I download it from the server 1, and how can I fix this?

Upvotes: 2

Views: 511

Answers (2)

Andrey Tyukin
Andrey Tyukin

Reputation: 44918

One of your servers probably attempts to transmit the file as text, and your ftp client also thinks that it receives text.

Here is an excerpt from the javadoc:

If the current file type is ASCII, the returned InputStream will convert line separators in the file to the local representation.

If you are on windows, every line break will be replaced by 'linebreak + cr', wreaking havoc on all data structures in the png file.

The expected number of bytes for this scenario is: 4686 * (1 + 1 / 256) = 4704.3046875 , because on average, every 256-th byte in a png file should look like an ASCII line break, and will therefore result in an extra added byte. Your file ends up having 4706 bytes, which is pretty close.

Setting file type to FTP.BINARY_FILE_TYPE should fix this: https://commons.apache.org/proper/commons-net/apidocs/org/apache/commons/net/ftp/FTPClient.html#setFileType(int)

Upvotes: 3

Martin Prikryl
Martin Prikryl

Reputation: 202272

FTPClient uses ascii mode by default.

You have to use binary mode to transfer binary files.

ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

Your current code can by chance work on some servers even in the ascii mode, if the server is using Windows EOL sequence, hence no conversion takes place. And even then probably only, if the file by chance does not contain any lone #13.

Upvotes: 4

Related Questions