Images downloaded from “some” servers with FTPClient are corrupted

大憨熊 提交于 2020-01-23 17:27:06

问题


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?


回答1:


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)




回答2:


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.



来源:https://stackoverflow.com/questions/48502993/images-downloaded-from-some-servers-with-ftpclient-are-corrupted

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!