java实现ftp文件上传
1、ftp文件上传步骤
1)连接ftp
2)检查工作目录是否存在
3)检查是否上传成功
4)完成任务后,断开ftp
2、具体如下,直接贴上核心代码:
A)导入核心pom依赖
<!--FTP包-->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.5</version>
</dependency>
<!--日志包-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.9</version>
</dependency>
B)这边直接贴上FTPTools工具类
package com.example.demo.ftp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import java.io.IOException;
import java.io.InputStream;
/**
* 通过FTP上传文件
*
* @Author zhengwd, 参考lvhaibao
* @Date 2021/12/21
*/
@Slf4j
public class FTPTools {
/**
* 设置私有不能实例化
*/
private FTPTools() {}
/**
* 上传
*
* @param hostname
* @param port
* @param username
* @param password
* @param workingPath 服务器的工作目录
* @param inputStream 文件的输入流
* @param saveName 要保存的文件名
* @return
*/
public static boolean upload(String hostname, int port, String username, String password, String workingPath, InputStream inputStream, String saveName) {
boolean flag = false;
FTPClient ftpClient = new FTPClient();
// 1、连接ftp
if (connect(ftpClient, hostname, port, username, password)) {
try {
// 2.检查工作目录是否存在
if (ftpClient.changeWorkingDirectory(workingPath)) {
// 3.检查是否上传成功
if (storeFile(ftpClient, saveName, inputStream)) {
flag = true;
// 4.完成任务,断开ftp
disconnect(ftpClient);
}
}
} catch (IOException e) {
log.error("工作目录不存在");
e.printStackTrace();
// 4.完成任务,断开ftp
disconnect(ftpClient);
}
}
return flag;
}
/**
* 断开连接
*
* @param ftpClient
* @throws Exception
*/
public static void disconnect(FTPClient ftpClient) {
if (ftpClient.isConnected()) {
try {
ftpClient.disconnect();
log.error("已关闭连接");
} catch (IOException e) {
log.error("没有关闭连接");
e.printStackTrace();
}
}
}
/**
* 测试是否能连接
*
* @param ftpClient
* @param hostname ip或域名地址
* @param port 端口
* @param username 用户名
* @param password 密码
* @return 返回真则能连接
*/
public static boolean connect(FTPClient ftpClient, String hostname, int port, String username, String password) {
boolean flag = false;
try {
ftpClient.connect(hostname, port);
// 原文章作者是将编码格式设置放置在这里的,我实际使用的时候,
// 在自己的ftp服务器是没问题,可能本地兼容utf-8,但是远程(其他人)服务器就会出现彩色乱码
// ftpClient.enterLocalPassiveMode();
// ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
// ftpClient.setControlEncoding("UTF-8");
if (ftpClient.login(username, password)) {
// 查了一些文章,需要ftp登录成功后再设置编码格式,否则编码格式无效,可能会出现文件内容损坏,例如彩色乱码之类的
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.setControlEncoding("UTF-8");
log.info("连接ftp成功");
flag = true;
} else {
log.error("连接ftp失败,可能用户名或密码错误");
try {
disconnect(ftpClient);
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (IOException e) {
log.error("连接失败,可能ip或端口错误");
e.printStackTrace();
}
return flag;
}
/**
* 上传文件
*
* @param ftpClient
* @param saveName 全路径。如/home/public/a.txt
* @param fileInputStream 输入的文件流
* @return
*/
public static boolean storeFile(FTPClient ftpClient, String saveName, InputStream fileInputStream) {
boolean flag = false;
try {
if (ftpClient.storeFile(saveName, fileInputStream)) {
flag = true;
log.error("上传成功");
disconnect(ftpClient);
}
} catch (IOException e) {
log.error("上传失败");
disconnect(ftpClient);
e.printStackTrace();
}
return flag;
}
}
C)测试类代码
package com.example.demo.ftp;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* @Author zhengwd, 参考lvhaibao
* @Date 2021/12/21
*/
public class MainTest {
public static void main(String[] args) throws FileNotFoundException {
// 服务器IP
String hostname = "";
// 端口号
int port = 21;
// 登录用户名
String username = "";
// 登录密码
String password = "";
// 文件转存文件夹路径
String workingPath = "/";
String str = "C:\\Users\\sourceFileName.pdf";
InputStream fileInputStream = new FileInputStream(new File(str));
String saveName = "targetFileName.pdf";
System.out.println(FTPTools.upload( hostname, port, username, password, workingPath, fileInputStream, saveName));
}
}
测试结果:
扩展
ftp的访问方式
ftp://ftp服务器ip
有需要身份校验的,输入账号密码进行校验
这时候就能看到文件上传到指定ftp服务器的指定位置了,如下:
有些人可能没有ftp服务器相关信息,请参照以下参考文章2自己搭建一个!
关于PDF文件出现文件损坏,彩色乱码
‘参考文章1’的方式在自己的ftp服务器传PDF文件是没问题的,可能本地兼容utf-8,但是远程(其他人)服务器就会出现彩色乱码,像这种:
知道是编码问题就是不知道怎么改,那时候很难受!
后来查到了‘参考文章3’,发现是字符编码设置的位置有问题,之前一直没有看到这一行字,走了不少弯路,如下:
原代码具体优化代码内容:
重试发现就可以了,开心到起飞~~~
需要批量处理时,代码的优化方案
FTPClient ftpClient = new FTPClient();
// 1 连接ftp
boolean connect = FTPTools.connect(ftpClient, hostName, port, userName, password);
if (connect) {
try {
// 2 检查工作目录是否存在
boolean isExist = ftpClient.changeWorkingDirectory(workingPath);
if (isExist) {
// TODO 批处理数据代码 数据获取
List<Map<String, Object>> list = new ArrayList<>();
int dataCount = list.size();
for (int i = 0; i < dataCount; i++) {
// TODO 流获取
InputStream fileInputStream = null;
String fileFtpName = "";
try {
// 3 检查是否上传成功
boolean upload = FTPTools.storeFileByConnOne(ftpClient, fileFtpName, fileInputStream);
log.info("进来了,序号:{},结果:{}", i, upload);
// TODO 上传成功的后续操作
} catch (Exception e) {
e.printStackTrace();
continue;
} finally {
// 关闭该文件流
if (fileInputStream != null) {
fileInputStream.close();
}
}
}
}
} catch (IOException e) {
log.error("工作目录不存在");
e.printStackTrace();
} finally {
// 关闭ftp连接
FTPTools.disconnect(ftpClient);
}
}
FTPTools新增方法,去掉断开ftp的方法,如下:
public static boolean storeFileByConnOne(FTPClient ftpClient, String saveName, InputStream fileInputStream) {
boolean flag = false;
try {
if (ftpClient.storeFile(saveName, fileInputStream)) {
flag = true;
log.error("上传成功");
// disconnect(ftpClient);
}
} catch (IOException e) {
log.error("上传失败");
// disconnect(ftpClient);
e.printStackTrace();
}
return flag;
}
这样就可以实现批量上传了(连接一次ftp,一直传,最后断开,节省频繁连接的开销)
参考文章:
Java使用FTP上传文件
快速搭建一个本地的FTP服务器
JAVA FTPClient相关问题(速度慢,中文乱码,内容丢失)解决办法