问题
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