这里我先提下FTP文件名乱码这个问题吧
(1)首先FTP是一种传输协议,它本身并不是一个服务器,只是我们通常称那些可以支持FTP协议的服务端 称之为 FTP服务器
(2)FTP协议中,默认文件名编码为ISO-8859-1,这就是如果我们上次文件时,文件名含中文,如果不做编码转换处理,就会导致文件名乱码的原因
关于乱码简述: 乱码的原因,归根结底就是 编码和解码方式不一致所导致的。
下面进入Spring使用FTP正题:1. 首先在application.yml中配置FTP的连接参数
#ftp连接配置 ftp: address: 127.0.0.1 port: 21 username: test password: test
2. 新建FTPProperties配置类
@Data
@Component
@ConfigurationProperties(prefix = "ftp")
public class FTPProperties {
private String address;
private Integer port;
private String username;
private String password;
}
3. 配置信息完成,接下来写FTP上传下载的工具类
package ftp;
import com.landa.exception.CustomException;
import ftp.config.FTPProperties;
import io.util.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.net.ftp.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.NoSuchFileException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Slf4j
@Component
public class FTPUtil {
@Autowired
private FTPProperties config;
//本地字符编码
private static String LOCAL_CHARSET="GBK";
//FTP默认文件名编码
private static String SERVER_CHARSET=FTPClient.DEFAULT_CONTROL_ENCODING;
//服务端UTF8的支持选项
private static String COMMAND_OPEN_UTF8="OPTS UTF8";
//开启状态
private static String OPEN_STATUS="ON";
//路径分隔符
private static final String SPECTOR="/";
//中文字符匹配正则
private static Pattern P = Pattern.compile("[u4e00-u9fa5]");
public FTPClient getFtpConnection()throws Exception{
FTPClient ftpClient = new FTPClient();
ftpClient.connect(config.getAddress(), config.getPort());
ftpClient.login(config.getUsername(),config.getPassword());
int reply=ftpClient.getReplyCode();
if(!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
log.error("FTP server refused connection");
}else{
if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(COMMAND_OPEN_UTF8, OPEN_STATUS))) {
LOCAL_CHARSET = "UTF-8";
}
}
//在设置了连接模式之后如果再调用任何连接方法,会重置连接模式为主动模式
ftpClient.enterLocalPassiveMode();
return ftpClient;
}
public void downloadToBrowser(String parentPath, String sourceName,String targetName, HttpServletResponse response)throws Exception{
InputStream inputStream= null;
OutputStream outputStream= null;
try {
//判断文件是否存在,存在则返回连接,否则抛出异常
FTPClient client = checkExists(parentPath, sourceName);
//获取文件输入流
inputStream = client.retrieveFileStream(new String(sourceName.getBytes(LOCAL_CHARSET),SERVER_CHARSET));
//设置流式响应头,以及设置文件名
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(targetName, "UTF-8"));
//获取响应流,write流到目标浏览器
outputStream = response.getOutputStream();
if (inputStream != null) {
byte[] bytes = new byte[1024];
int readBytes;
while ((readBytes = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, readBytes);
}
}
if (inputStream != null) {
inputStream.close();
}
if (!client.completePendingCommand()) {
client.logout();
client.disconnect();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(null!=outputStream){
outputStream.close();
}
if (null!= inputStream) {
inputStream.close();
}
}
}
public boolean deleteFile(String path, String fileName) throws Exception {
//获取连接
FTPClient ftp = getFtpConnection();
//切换工作目录至文件所在目录
boolean flag = ftp.changeWorkingDirectory(new String(path.getBytes(LOCAL_CHARSET), SERVER_CHARSET));
if (!flag) {
throw new CustomException("文件路径[" + path + "]不正确,或没有操作权限");
}
//删除文件
return ftp.deleteFile(new String(fileName.getBytes(LOCAL_CHARSET),SERVER_CHARSET));
}
//获取文件输入流
public InputStream getFileInputStream(String parentPath,String sourceName)throws Exception{
FTPClient client = checkExists(parentPath, sourceName);
return client.retrieveFileStream(new String(sourceName.getBytes(LOCAL_CHARSET),SERVER_CHARSET));
}
//获取文件输出流
public OutputStream getFileOutPutStream(String parentPath,String sourceName)throws Exception{
FTPClient client = checkExists(parentPath, sourceName);
return client.storeFileStream(new String(sourceName.getBytes(LOCAL_CHARSET),SERVER_CHARSET));
}
//判断文件是否存在
private FTPClient checkExists(String parentPath, String sourceName) throws Exception {
FTPClient client = getFtpConnection();
parentPath = parentPath.replaceAll("\\", "/");
if (!parentPath.endsWith(SPECTOR)) {
parentPath += SPECTOR;
}
String filePath = parentPath + sourceName;
client.changeWorkingDirectory(parentPath);
if (!existFile(filePath)) {
throw new FileNotFoundException("文件不存在");
}
return client;
}
public void uploadFile(InputStream inputStream,String parentPath,String ftpFileName)throws Exception{
FTPClient client=null;
try {
parentPath=parentPath.replaceAll("\\","/");
try {
client=getFtpConnection();
} catch (Exception e) {
throw new RuntimeException("FTP连接失败");
}
//若目标目录不存在则创建,并切换工作目录
createDirIfNotExists(client,parentPath);
client.setFileType(FTP.BINARY_FILE_TYPE);
if(!client.storeFile(new String(ftpFileName.getBytes(LOCAL_CHARSET),SERVER_CHARSET),inputStream)){
throw new CustomException("upload failed");
}
client.logout();
} catch (Exception e) {
throw new CustomException(e.getMessage(),e);
} finally {
if(null!=inputStream){
inputStream.close();
}
if(null!=client&&client.isConnected()){
client.disconnect();
}
}
}
private void createDirIfNotExists(FTPClient ftpClient,String path)throws Exception{
//判断FTP连接是否关闭,如果关闭则新建连接
if(new File(path).isDirectory()){
String[] dirs=path.split("/");
for (String dir:dirs) {
dir=new String(dir.getBytes(LOCAL_CHARSET),SERVER_CHARSET);
if(ftpClient.changeWorkingDirectory(dir)){
continue;
}
if(ftpClient.makeDirectory(dir)){
ftpClient.changeWorkingDirectory(dir);
}else{
throw new CustomException("目录["+path+"]创建失败");
}
}
}
}
public void createDirIfNotExists(String path)throws Exception{
FTPClient client=getFtpConnection();
createDirIfNotExists(client,path);
}
public static boolean isContainChinese(String str) {
Matcher m = P.matcher(str);
return m.find();
}
// 判断ftp服务器文件是否存在
private boolean existFile(FTPClient client,String path) throws Exception {
boolean flag = false;
FTPFile[] ftpFileArr = client.listFiles(path);
if (ftpFileArr.length > 0) {
flag = true;
}
return flag;
}
public boolean existFile(String path){
FTPClient ftpClient=null;
try {
ftpClient=getFtpConnection();
boolean exists=existFile(ftpClient,path);
ftpClient.logout();
return exists;
} catch (Exception e) {
throw new CustomException(e.getMessage(),e);
} finally {
if(null!=ftpClient&&ftpClient.isConnected()){
try {
ftpClient.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
希望对您有帮助,也欢迎大家提出宝贵的建议



