1、创建连接工厂
private static int threadNum = 10;
private ArrayBlockingQueue<FtpConnection> arrayBlockingQueue =
new ArrayBlockingQueue<>(threadNum);
public FtpFactory(){
for(int i = 0; i< threadNum; i++){
arrayBlockingQueue.offer(new FtpConnection());
}
}
public FtpConnection getFtp(){
FtpConnection poll = null;
try {
poll = arrayBlockingQueue.take();
} catch (Exception e) {
e.printStackTrace();
}
return poll;
}
public boolean relase(FtpConnection ftp){
return arrayBlockingQueue.offer(ftp);
}
public void remove(FtpConnection ftp){
arrayBlockingQueue.remove(ftp);
}
public void close(){
for(FtpConnection connection : arrayBlockingQueue){
try {
connection.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2、写一个FTP的工具类
public static synchronized List<UploadFileResult> uploadFile(String ftpPath, File[] listFiles,int threadNum) {
ExecutorService executorService = Executors.newFixedThreadPool(threadNum);//可以自定义threadNum
List<Future> results = new ArrayList<>();
FtpFactory factory = new FtpFactory();
Long length = 0L;
for (File file : listFiles) {
FtpConnection ftp = factory.getFtp();
UploadTask task = new UploadTask(factory,ftp, file, ftpPath, file.getName());
Future future = executorService.submit(task);
results.add(future);
length += file.length();
}
System.out.println("length=" + length);
List<UploadFileResult> listResults = new ArrayList<>();
for (Future result : results) {
try {
UploadFileResult uploadFileResult = (UploadFileResult)result.get(60, TimeUnit.MINUTES);
listResults.add(uploadFileResult);
} catch (Exception e) {
e.printStackTrace();
}finally {
factory.close();
}
}
factory.close();
executorService.shutdown();
return listResults;
}
3、可自定义返回结果集
private String ftpPathFileName; //ftp文件路径名称
private boolean result; //是否上传成功
private File file;
public UploadFileResult(String ftpPathFileName, boolean result, File file) {
this.ftpPathFileName = ftpPathFileName;
this.result = result;
this.file = file;
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public String getFtpPathFileName() {
return ftpPathFileName;
}
public void setFtpPathFileName(String ftpPathFileName) {
this.ftpPathFileName = ftpPathFileName;
}
public boolean isResult() {
return result;
}
public void setResult(boolean result) {
this.result = result;
}
}
4、创建上传的task
public class UploadTask implements Callable{
private File file;
private FtpConnection ftpConnection;
private String ftpPath;
private String fileName;
private FtpFactory factory;
public UploadTask(FtpFactory factory, FtpConnection ftpConnection, File file, String ftpPath, String fileName){
this.factory = factory;
this.ftpConnection = ftpConnection;
this.file = file;
this.ftpPath = ftpPath;
this.fileName = fileName;
}
@Override
public UploadFileResult call() throws Exception {
UploadFileResult result = null;
try{
if(ftpConnection == null){
result = new UploadFileResult(file.getAbsolutePath(),false,file);
return result;
}
if(!ftpConnection.isConnected()){
factory.remove(ftpConnection);
ftpConnection = new FtpConnection();
}
FileInputStream inputStream = new FileInputStream(file);
ftpConnection.uploadFile(ftpPath, fileName, inputStream);
result = new UploadFileResult(ftpPath + "/" + file.getName(),true,file);
}catch(IOException e){
result = new UploadFileResult(ftpPath + "/" + file.getName(),false,file);
e.printStackTrace();
}finally{
factory.relase(ftpConnection);
}
return result;
}
}
5、创建FTP连接类
private FTPClient ftpClient = new FTPClient();
private boolean isConnected = false;
public FtpConnection(){
isConnected = false;
try {
initConnect("myip", "myport", "myFTPUserName", "myFTPPassWord");
} catch (IOException e) {
e.printStackTrace();
}
}
private void initConnect(String host, int port, String userName, String password) throws IOException {
ftpClient.connect(host, port);
int reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
disconnect();
}
if (!ftpClient.login(userName, password)) {
isConnected = false;
disconnect();
} else {
isConnected = true;
}
}
static String LOCAL_CHARSETUTF_8 = "UTF-8";
static String SERVER_CHARSET_ISO = "ISO-8859-1";
static String SERVER_CHARSETGBK = "GBK";
private static String encodingPath(String path) {
return StringUtils.toEncodedString(path.replaceAll("//", "/").getBytes(), StandardCharsets.UTF_8);
}
public void uploadFile(String ftpPath,String ftpFileName, FileInputStream inputStream) throws IOException {
if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("\"OPTS UTF8\", \"ON\""))){
ftpClient.setControlEncoding(LOCAL_CHARSETUTF_8);
}else {
ftpClient.setControlEncoding(SERVER_CHARSETGBK);
}
setWorkingDirectory(ftpPath);
ftpClient.makeDirectory(ftpPath);
ftpClient.changeWorkingDirectory(ftpPath);
try {
ftpClient.enterLocalPassiveMode();
if (!ftpClient.storeFile(ftpFileName, inputStream)) {
throw new RuntimeException("上传失败");
}
inputStream.close();
}catch (Exception e){
e.getStackTrace();
}finally {
try {
inputStream.close();
} catch (IOException ex) {
}
}
}
public void disconnect() throws IOException {
if (ftpClient.isConnected()) {
try {
ftpClient.logout();
ftpClient.disconnect();
isConnected = false;
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
private boolean setWorkingDirectory(String dir) {
if (!isConnected) {
return false;
}
try {
if(createDirecroty(dir)){
return ftpClient.changeWorkingDirectory(dir);
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public boolean isConnected(){
return isConnected;
}
private boolean createDirecroty(String remote) throws IOException {
boolean success = true;
String directory = remote.substring(0, remote.lastIndexOf("/") + 1);
if (!directory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(new String(directory))) {
int start = 0;
int end = 0;
if (directory.startsWith("/")) {
start = 1;
} else {
start = 0;
}
end = directory.indexOf("/", start);
while (true) {
String subDirectory = new String(remote.substring(start, end));
if (!ftpClient.changeWorkingDirectory(subDirectory)) {
if (ftpClient.makeDirectory(subDirectory)) {
ftpClient.changeWorkingDirectory(subDirectory);
} else {
return false;
}
}
start = end + 1;
end = directory.indexOf("/", start);
if (end <= start) {
break;
}
}
}
return success;
}
6、Controller
@RequestMapping("/uploadThreads")
public String uploadThreads(String loalPath,String ftpPath) throws IOException {
File parentFile = new File(loalPath);
List<UploadFileResult> resultLists = FtpUtils.uploadFile(ftpPath,parentFile.listFiles(),10);//开启10个线程
if(resultLists != null && resultLists.size() > 0){
return "success";
}else{return "error";}
}