java ftp 中文乱码_FTP 中文乱码解决方案-JAVA

概述

解决 FTPClient下载中文路径和中文文件名乱码的方案

解决中文的乱码问题主要以下几点:

根据FTP服务器配置编码设置客户端的编码方式ftpClient.setControlEncoding();

在判断FTP上目录是否存在对目录进行编码;new String(remotePath.getBytes(), FTP.DEFAULT_CONTROL_ENCODING)

下载文件时,文件名和路径要进行编码否则下载乱码remoteFileName = new String(remoteFileName.getBytes(), FTP.DEFAULT_CONTROL_ENCODING)

总结:乱码的主要问题是客户端编码和FTP服务端编码不一致导致的,在使用ftpClien时进行编码

参考代码

maven的是这个引入代码包

commons-net

commons-net

3.3

连接FTP服务器

public void login() throws FTPUtilsException {

ftpClient = new org.apache.commons.net.ftp.FTPClient();

try {

try {

ftpClient.connect(this.ftpAddress, this.ftpPort);

} catch (Exception e ) {

throw new FTPException("连接FTP服务器“" + this.ftpAddress +"” 失败", e);

}

try {

ftpClient.login(this.ftpUsername, this.ftpPassword);

} catch (Exception e) {

throw new FTPException("登录FTP服务器“" + this.ftpAddress +"” 失败", e);

}

ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);

if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {

// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).

localCharset = CHARSET_UTF8;

}

ftpClient.setControlEncoding(localCharset);

//限制缓冲区大小

ftpClient.setBufferSize(BUFFER_SIZE);

int reply = ftpClient.getReplyCode();

if (!FTPReply.isPositiveCompletion(reply)) {

closeConnect();

throw new FTPException("连接FTP服务器“" + this.ftpAddress + "”失败");

}

ftpClient.enterLocalPassiveMode(); // 设置被动模式,开通一个端口来传输数据

ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

} catch (Exception e) {

closeConnect();

throw new FTPUtilsException("登录FTP服务器失败", e);

}

}

关闭FTP连接

public void closeConnect() {

if (ftpClient != null && ftpClient.isConnected()) {

try {

ftpClient.logout();

ftpClient.disconnect();

} catch (IOException e) {

ThrowableManager.process(e);

LOGGER.error(LogProperty.LOGTYPE_DETAIL,"关闭FTP连接败", e);

}

}

}

下载该目录下所有文件到本地

/**

* 下载该目录下所有文件到本地

*

* @param ftpPath FTP服务器上的相对路径,例如:test/123

* @param localPath 保存文件到本地的路径,例如:D:/test

* @return 成功返回true,否则返回false

*/

public Boolean downLoadDirectory(String ftpPath, String localPath) throws FTPUtilsException {

return downLoadDirectory(ftpPath, localPath, true);

}

/**

* 下载该目录下所有文件到本地

*

* @param ftpPath FTP服务器上的相对路径,例如:test/123

* @param localPath 保存文件到本地的路径,例如:D:/test 全路径

* @param isRepeatDownLoad 是否重新下载

* @return 成功返回true,否则返回false

*/

public Boolean downLoadDirectory(String ftpPath, String localPath, Boolean isRepeatDownLoad) throws FTPUtilsException {

if (ftpClient != null) {

try {

String remotePath = basePath + ftpPath;// changeEncoding(basePath + ftpPath);

LOGGER.info(LogProperty.LOGTYPE_DETAIL,"文件夹路径,NfsPath=" + localPath);

File doc = new File(localPath);

if (!doc.exists()) {

doc.mkdirs();

// FileOperation.setFullAccessPermissions(localPath);

}

// 判断FTP上目录是否存在

String tmpFtpPath = new String(remotePath.getBytes(), FTP.DEFAULT_CONTROL_ENCODING);

if (!ftpClient.changeWorkingDirectory(tmpFtpPath)) {

LOGGER.info(LogProperty.LOGTYPE_DETAIL, basePath + tmpFtpPath + DIR_NOT_EXIST);

return Boolean.FALSE;

}

FTPFile[] ftpFiles = ftpClient.listFiles(tmpFtpPath);

for(FTPFile f: ftpFiles) {

String ftpName = new String(f.getName().getBytes(),CHARSET_UTF8);

LOGGER.info(LogProperty.LOGTYPE_DETAIL,"ftp文件=" +ftpName);

if(f.isFile()) {

downloadFile(ftpName, localPath, ftpPath);

} else {

String dirFtpPath = ftpPath + '/' + ftpName;

String dirlocalPath = localPath + File.separator + ftpName;

downLoadDirectory(dirFtpPath, dirlocalPath);

}

}

} catch (Exception e) {

throw new FTPUtilsException("下载FTP目录“ "+ ftpPath +"”失败", e);

}

}

return Boolean.TRUE;

}

下载文件

/***

* 下载文件

* @param remoteFileName 待下载文件名称

* @param localDires 下载到当地那个路径下

* @param remoteDownLoadPath remoteFileName所在的路径

* */

public boolean downloadFile(String remoteFileName, String localDires,

String remoteDownLoadPath) throws FTPUtilsException {

String strFilePath = localDires + File.separator + remoteFileName;

LOGGER.info(LogProperty.LOGTYPE_DETAIL,"开始下载文件" + strFilePath);

BufferedOutputStream outStream = null;

boolean success = false;

InputStream inputStream = null;

try {

String tmpFtpPath = new String(remoteDownLoadPath.getBytes(), FTP.DEFAULT_CONTROL_ENCODING);

if (!ftpClient.changeWorkingDirectory(tmpFtpPath)) {

LOGGER.warn(LogProperty.LOGTYPE_DETAIL, basePath + tmpFtpPath + DIR_NOT_EXIST);

return Boolean.FALSE;

}

LOGGER.info(LogProperty.LOGTYPE_DETAIL ,remoteFileName + "开始下载....");

/解决中文乱码/

// String remoteFileName2 = new String(remoteFileName.getBytes(), FTP.DEFAULT_CONTROL_ENCODING);

// inputStream = ftpClient.retrieveFileStream(remoteFileName2);

// copyInputStreamToFile(inputStream, FileUtils.getFile(strFilePath));

// inputStream.close();

// ftpClient.completePendingCommand();

/中文乱码/

outStream = new BufferedOutputStream(new FileOutputStream(strFilePath));

// 解决中文乱码

remoteFileName = new String(remoteFileName.getBytes(), FTP.DEFAULT_CONTROL_ENCODING);

success = ftpClient.retrieveFile(remoteFileName, outStream);

/中文乱码/

if (success) {

LOGGER.info(LogProperty.LOGTYPE_DETAIL, remoteFileName + "成功下载到" + strFilePath);

return success;

}

}catch (Exception e) {

LOGGER.error(LogProperty.LOGTYPE_DETAIL, remoteFileName + "成功下载失败“" + strFilePath +"”", e);

throw new FTPUtilsException(remoteFileName + "下载失败");

}finally {

if(inputStream != null) {

try {

inputStream.close();

} catch (IOException ex) {

ThrowableManager.process(ex);

}

}

if (null != outStream) {

try {

outStream.flush();

outStream.close();

}catch (IOException e) {

e.printStackTrace();

}

}

}

return success;

}

检查FTP目录是否存在及下面是否存在文件

/**

* 检查FTP目录是否存在及下面是否存在文件

*

* @param ftpPath FTP服务器文件相对路径,例如:test/123

* @return void

*/

public void checkDirFtp(String ftpPath) throws FTPUtilsException {

String path = changeEncoding(basePath + ftpPath);

if (ftpClient != null) {

try {

// 判断是否存在该目录

if (!ftpClient.changeWorkingDirectory(path.length() == 0 ? "/" : path)) {

throw new FTPUtilsException("FTP上不不存在此目录 “" + path + "”");

}

} catch (IOException e ) {

throw new FTPUtilsException("FTP上不不存在此目录 “" + path + "”");

}

try {

FTPFile[] ftpFiles = ftpClient.listFiles();

if (ftpFiles.length == 0) {

throw new FTPUtilsException("FTP目录 “ "+ftpPath+" ” 下文件为空,禁止操作!");

}

} catch (IOException e ) {

throw new FTPUtilsException("FTP上不不存在此目录,“" + path + "”!");

}

} else {

throw new FTPUtilsException("请先登录FTP服务器!");

}

}

main

public static void main(String[] args) {

String ftpAddress = "";

int ftpPort = 2222;

String ftpuser = "";

String ftppwd = "";

String ftpPath = "";

String savPath = "D:\\Temp\\ftp";

FTPUtils ftpUtils = new FTPUtils(ftpAddress, ftpPort, ftpuser, ftppwd);

try {

ftpUtils.login();

ftpUtils.downLoadDirectory(ftpPath, savPath);

} catch (Exception e) {

e.printStackTrace();

} finally {

ftpUtils.closeConnect();

}

System.exit(-1);

}

FTPUtils 参考代码

public class FTPUtils {

import java.io.BufferedOutputStream;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import org.apache.commons.net.ftp.FTP;

import org.apache.commons.net.ftp.FTPClient;

import org.apache.commons.net.ftp.FTPFile;

import org.apache.commons.net.ftp.FTPReply;

/**

* 日志对象s

**/

private static final Log LOGGER = LogFactory.getLogger(FTPUtils.class);

/**

* 该目录不存在

*/

public static final String DIR_NOT_EXIST = "该目录不存在";

/**

* "该目录下没有文件

*/

public static final String DIR_CONTAINS_NO_FILE = "该目录下没有文件";

/**

* FTP地址

**/

private String ftpAddress;

/**

* FTP端口

**/

private int ftpPort = 521;

/**

* FTP用户名

**/

private String ftpUsername;

/**

* FTP密码

**/

private String ftpPassword;

/**

* FTP基础目录

**/

private String basePath = "";

/**

* 本地字符编码

**/

private static String localCharset = "GBK";

/**

* FTP协议里面,规定文件名编码为iso-8859-1

**/

private static String serverCharset = "ISO-8859-1";

/**

* UTF-8字符编码

**/

private static final String CHARSET_UTF8 = "UTF-8";

/**

* OPTS UTF8字符串常量

**/

private static final String OPTS_UTF8 = "OPTS UTF8";

/**

* 设置缓冲区大小4M

**/

private static final int BUFFER_SIZE = 1024 * 1024 * 4;

/**

* FTPClient对象

**/

private static org.apache.commons.net.ftp.FTPClient ftpClient = null;

public FTPUtils(String ftpAddress, int ftpPort, String ftpUsername, String ftpPassword) {

this.ftpAddress = ftpAddress;

this.ftpPort = ftpPort;

this.ftpUsername = ftpUsername;

this.ftpPassword = ftpPassword;

}

}

/**

* FTP服务器路径编码转换

*

* @param ftpPath FTP服务器路径

* @return String

*/

private static String changeEncoding(String ftpPath) {

String directory = null;

try {

if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(OPTS_UTF8, "ON"))) {

localCharset = CHARSET_UTF8;

}

directory = new String(ftpPath.getBytes(localCharset), serverCharset);

} catch (Exception e) {

LOGGER.error(LogProperty.LOGTYPE_DETAIL, "路径编码转换失败", e);

}

return directory;

}

FTP异常类

public class FTPUtilsException extends Exception {

public FTPUtilsException(String message) {

super(message);

}

public FTPUtilsException(String message, Throwable cause) {

super(message, cause);

}

}

你可能感兴趣的:(java,ftp,中文乱码)