Java 图片下载自;“一些”;具有FTPClient的服务器已损坏

Java 图片下载自;“一些”;具有FTPClient的服务器已损坏,java,ftp,apache-commons-net,Java,Ftp,Apache Commons Net,我需要用Java从FTP服务器下载.png文件。 我有3个不同的服务器,每个服务器都包含一个文件夹,其中包含完全相同的.png文件 在服务器1上: 如果我使用FTPClient(apache.commons.net.ftp)下载存储在此服务器上的4686字节的.png文件,我会得到一个4706字节的.png文件,无法打开它。 如果我用Total Commander下载它,我会得到一个4686字节的.png文件,我可以打开它 在服务器2和3上: 使用FTPClient和Total Commande

我需要用Java从FTP服务器下载.png文件。 我有3个不同的服务器,每个服务器都包含一个文件夹,其中包含完全相同的.png文件

在服务器1上:
如果我使用
FTPClient
(apache.commons.net.ftp)下载存储在此服务器上的4686字节的.png文件,我会得到一个4706字节的.png文件,无法打开它。 如果我用Total Commander下载它,我会得到一个4686字节的.png文件,我可以打开它

在服务器2和3上:
使用
FTPClient
和Total Commander,我在这两种情况下都会得到一个4686字节的文件,我可以毫无问题地打开它

我的代码:

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();
}

为什么我的文件只有在从服务器1下载时才有这些“额外字节”,我如何解决这个问题?

您的一台服务器可能试图将文件作为文本传输,而您的ftp客户端也认为它接收到文本

以下是javadoc的摘录:

如果当前文件类型为ASCII,则返回的InputStream 将文件中的行分隔符转换为本地分隔符 代表性

如果您在windows上,则每个换行符都将替换为“linebreak+cr”,这将对png文件中的所有数据结构造成严重破坏

这种情况下的预期字节数为:4686*(1+1/256)=4704.3046875,因为png文件中平均每256个字节看起来都像ASCII换行符,因此会额外增加一个字节。您的文件最终有4706个字节,这非常接近


将文件类型设置为FTP。二进制文件类型应能解决此问题:

您的一台服务器可能试图将文件作为文本传输,而您的FTP客户端也认为它接收文本

以下是javadoc的摘录:

如果当前文件类型为ASCII,则返回的InputStream 将文件中的行分隔符转换为本地分隔符 代表性

如果您在windows上,则每个换行符都将替换为“linebreak+cr”,这将对png文件中的所有数据结构造成严重破坏

这种情况下的预期字节数为:4686*(1+1/256)=4704.3046875,因为png文件中平均每256个字节看起来都像ASCII换行符,因此会额外增加一个字节。您的文件最终有4706个字节,这非常接近


将文件类型设置为FTP。二进制文件类型应解决此问题:

FTPClient
默认使用ascii模式

您必须使用二进制模式来传输二进制文件

ftpClient.setFileType(FTP.BINARY_FILE_TYPE);


如果服务器使用Windows EOL序列,则当前代码可能会在某些服务器上工作,即使在ascii模式下也是如此,因此不会发生转换。即使如此,也可能只有在文件碰巧不包含任何单独的#13的情况下。

FTPClient
默认使用ascii模式

您必须使用二进制模式来传输二进制文件

ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

如果服务器使用Windows EOL序列,则当前代码可能会在某些服务器上工作,即使在ascii模式下也是如此,因此不会发生转换。即使是这样,也可能只有在文件碰巧不包含任何单独的#13的情况下