之前删除FTP指定文件夹下文件一直失败,找了半天发现是文件名的问题。
使用ftpclient.deletefile(fileName)删除一直有问题
开始猜测是权限原因,于是用ftp工具尝试删除,发现可以删除。
那就有问题了。
原因:
FTP协议里面,规定文件名编码为iso-8859-1,所以目录名或文件名包含中文需要转码。
解决方案:
将中文的目录或文件名转为iso-8859-1编码的字符。参考代码:
boolean dele = ftp.deleteFile(new String(fileName.getBytes("utf-8"),"iso-8859-1"));
然后就能删除成功了。
FTP工具类:
package com.cetc.file.admin.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class FtpUtil {
public static List<String> list = new ArrayList<>();
public static Integer getFTPClient(String ftpHost, Integer ftpPort, String ftpUserName, String ftpPassword){
//1:成功链接 0:链接失败
Integer status ;
FTPClient ftpClient = null;
try {
ftpClient = new FTPClient();
ftpClient.setConnectTimeout(60000);
if(ftpPort != null){
ftpClient.connect(ftpHost, ftpPort);// 连接FTP服务器
}else {
ftpClient.connect(ftpHost);// 连接FTP服务器
}
if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
if (ftpClient.login(ftpUserName, ftpPassword)) {// 登陆FTP服务器
if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(
"OPTS UTF8", "ON"))) {// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
ftpClient.setControlEncoding("UTF-8");
}else {
ftpClient.setControlEncoding("GBK");
}
ftpClient.enterLocalPassiveMode();// 设置被动模式
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);// 设置传输的模式,以二进制流的方式读取
ftpClient.enterLocalPassiveMode();
System.out.println("FTP服务连接成功!");
status = 1;
}else {
System.out.println("FTP服务用户名或密码错误!");
status = 0;
disConnection(ftpClient);
}
}else {
System.out.println("连接到FTP服务失败!");
status = 0;
disConnection(ftpClient);
}
} catch (SocketException e) {
e.printStackTrace();
status = 0;
disConnection(ftpClient);
System.out.println("FTP的IP地址可能错误,请正确配置。");
} catch (IOException e) {
e.printStackTrace();
status = 0;
disConnection(ftpClient);
System.out.println("FTP的端口错误,请正确配置。");
}finally {
disConnection(ftpClient);
}
return status;
}
/**
* 关闭FTP服务链接
* @throws IOException
*/
public static void disConnection(FTPClient ftpClient){
try {
if(ftpClient.isConnected()){
ftpClient.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 链接ftp
* @param ftpHost
* @param ftpUserName
* @param ftpPassword
* @param ftpPort
* @return
*/
public static FTPClient getFTPClients(String ftpHost, String ftpUserName,
String ftpPassword, int ftpPort) {
FTPClient ftpClient = new FTPClient();
try {
ftpClient = new FTPClient();
ftpClient.connect(ftpHost, ftpPort);// 连接FTP服务器
ftpClient.login(ftpUserName, ftpPassword);// 登陆FTP服务器
ftpClient.setBufferSize(1024);
if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(
"OPTS UTF8", "ON"))) {// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
ftpClient.setControlEncoding("UTF-8");
}else {
ftpClient.setControlEncoding("GBK");
}
ftpClient.enterLocalPassiveMode();// 设置被动模式
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);// 设置传输的模式,以二进制流的方式读取
ftpClient.enterLocalPassiveMode();
if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
ftpClient.disconnect();
log.error("未连接到FTP,用户名或密码错误。");
} else {
log.info("FTP connection success");
}
} catch (SocketException e) {
e.printStackTrace();
log.error("FTP的IP地址可能错误,请正确配置。");
} catch (IOException e) {
log.error("FTP的IP地址可能错误,请正确配置。");
}
return ftpClient;
}
/**
* 从FTP服务器上下载文件
*
* @param name ftp服务器文件路径,以/dir形式开始
* @param localDirectoryAndFileName 保存到本地的目录
* @return
*/
public static List<String> get(FTPClient ftpClient, String name, String localDirectoryAndFileName) {
ftpClient.enterLocalPassiveMode(); // Use passive mode as default
try {
list.clear();
List<String> files = List(ftpClient, name);
for(String ftpDirectoryAndFileName : files){
// 将路径中的斜杠统一
char[] chars = ftpDirectoryAndFileName.toCharArray();
StringBuffer sbStr = new StringBuffer(256);
for (int i = 0; i < chars.length; i++) {
if ('\\' == chars[i]) {
sbStr.append('/');
} else {
sbStr.append(chars[i]);
}
}
ftpDirectoryAndFileName =sbStr.toString();
String filePath = ftpDirectoryAndFileName.substring(0, ftpDirectoryAndFileName.lastIndexOf("/"));
String fileName = ftpDirectoryAndFileName.substring(ftpDirectoryAndFileName.lastIndexOf("/") + 1);
changeDir(ftpClient,filePath);
ftpClient.retrieveFile(new String(fileName.getBytes(), "iso-8859-1"),
new FileOutputStream(localDirectoryAndFileName+fileName)); // download
/*ftpClient.changeWorkingDirectory("/");*/
System.out.println(ftpClient.printWorkingDirectory());
if(ftpClient!=null){
boolean b = ftpClient.deleteFile(new String(fileName.getBytes("utf-8"),"iso-8859-1"));
System.out.println("删除文件"+b);
}else {
log.error("FTP链接关闭");
}
// file
System.out.println(ftpClient.getReplyString()); // check result
System.out.println("从ftp服务器上下载文件:" + ftpDirectoryAndFileName + ", 保存到:" + localDirectoryAndFileName);
}
return list;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 层层切换工作目录
*
* @param ftpPath 目的目录
* @return 切换结果
*/
public static boolean changeDir(FTPClient ftpClient,String ftpPath) {
if (!ftpClient.isConnected()) {
return false;
}
try {
// 将路径中的斜杠统一
char[] chars = ftpPath.toCharArray();
StringBuffer sbStr = new StringBuffer(256);
for (int i = 0; i < chars.length; i++) {
if ('\\' == chars[i]) {
sbStr.append('/');
} else {
sbStr.append(chars[i]);
}
}
ftpPath = sbStr.toString();
if (ftpPath.indexOf('/') == -1) {
// 只有一层目录
ftpClient.changeWorkingDirectory(new String(ftpPath.getBytes(), "iso-8859-1"));
} else {
// 多层目录循环创建
String[] paths = ftpPath.split("/");
for (int i = 0; i < paths.length; i++) {
ftpClient.changeWorkingDirectory(new String(paths[i].getBytes(), "iso-8859-1"));
}
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 递归获取文件夹下文件
* @param ftpClient
* @param pathName
* @return
* @throws IOException
*/
public static List<String> List(FTPClient ftpClient, String pathName) throws IOException{
if (pathName.startsWith("/") && !pathName.contains(".")) {//更换目录到当前目录
ftpClient.changeWorkingDirectory(pathName);
FTPFile[] files= ftpClient.listFiles();
for(FTPFile file : files) {
if(file.isFile()) {
list.add(pathName+File.separator+file.getName());
}else if(file.isDirectory()) {//需要加此判断。否则,ftp默认将‘项目文件所在目录之下的目录(./)’与‘项目文件所在目录向上一级目录下的目录(../)’都纳入递归,这样下去就陷入一个死循环了。需将其过滤掉。
if (!".".equals(file.getName()) && !"..".equals(file.getName())) {
List(ftpClient,"/"+pathName+"/"+file.getName());
}
}
}
}else{
list.add(pathName);
}
return list;
}
}