您的位置:首页 > 编程语言 > Java开发

Java使用FTPClient连接文件服务器并做相应操作(代码)

2018-02-23 00:00 615 查看
/**
*
*/
package com.common.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.lang.NullArgumentException;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

import com.common.DateUtils;

/**
* FTP客户端工具类
* @author luolin
*
* @version $id:FTPClientUtils.java,v 0.1 2015年11月13日 下午4:18:07 luolin Exp $
*/
public class FTPClientUtil {

private static final Logger LOGGER = Logger.getLogger(FTPClientUtil.class);

/**
* 连接文件服务器
* @param addr 文件服务器地址
* @param port 端口
* @param username 用户名
* @param password 密码
* @throws Exception
*/
public static FTPClient connect(String addr, int port, String username, String password) {
LOGGER.info("【连接文件服务器】addr = " + addr + " , port : " + port + " , username = " + username + " , password = "
+ password);

FTPClient ftpClient = new FTPClient();
try {
// 连接
ftpClient.connect(addr, port);
// 登录
ftpClient.login(username, password);
// 被动模式:每次数据连接之前,ftp client告诉ftp server开通一个端口来传输数据(参考资料:FTP主动/被动模式的解释)
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
} catch (Exception e) {
LOGGER.error("【连接文件服务器失败】", e);
throw new RuntimeException("连接文件服务器失败");
}
// 判断文件服务器是否可用??
if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
closeConnection(ftpClient);
}
return ftpClient;
}

/**
* 连接文件服务器
* @param addr 文件服务器地址
* @param port 端口
* @param username 用户名
* @param password 密码
* @param workingDirectory 目标连接工作目录
* @throws Exception
*/
public static FTPClient connect(String addr, int port, String username, String password, String workingDirectory)
throws Exception {
FTPClient ftpClient = connect(addr, port, username, password);
changeWorkingDirectory(workingDirectory, ftpClient);
return ftpClient;
}

/**
* 关闭连接,使用完连接之后,一定要关闭连接,否则服务器会抛出 Connection reset by peer的错误
* @throws IOException
*/
public static void closeConnection(FTPClient ftpClient) {
LOGGER.info("【关闭文件服务器连接】");
if (ftpClient == null) {
return;
}

try {
ftpClient.disconnect();
} catch (IOException e) {
LOGGER.error("【关闭连接失败】", e);
throw new RuntimeException("关闭连接失败");
}
}

/**
* 切换工作目录
* @param directory 目标工作目录
* @param ftpClient
* @throws IOException
*/
public static void changeWorkingDirectory(String directory, FTPClient ftpClient) {
LOGGER.info("【切换工作目录】directory : " + directory);
baseValidate(ftpClient);
// 切换到目标工作目录
try {
if (!ftpClient.changeWorkingDirectory(directory)) {
ftpClient.makeDirectory(directory);
ftpClient.changeWorkingDirectory(directory);
}
} catch (Throwable e) {
LOGGER.error("【切换工作目录失败】", e);
throw new RuntimeException("切换工作目录失败");
}
}

/**
* 上传文件/文件夹
* @param file 上传的文件或文件夹
* @return 文件存放的路径以及文件名
* @throws Exception
*/
public static void upload(File file, FTPClient ftpClient) throws Exception {
if (file == null) {
LOGGER.warn("【存储的文件为空】");
throw new RuntimeException("上传文件为空");
}
LOGGER.info("【上传文件/文件夹】file : " + file.getName());
baseValidate(ftpClient);
// 是文件,直接上传
if (!file.isDirectory()) {
storeFile(new File(file.getPath()), ftpClient);
return;
}

changeWorkingDirectory(file.getName(), ftpClient);
// 文件夹,递归上传所有文件
for (File item : file.listFiles()) {
if (!item.isDirectory()) {
storeFile(item, ftpClient);
continue;
}
upload(item, ftpClient);
ftpClient.changeToParentDirectory();
}
}

/**
* 删除文件
* @param fileName 要删除的文件地址
* @return true/false
* @throws IOException
*/
public static boolean delete(String fileName, FTPClient ftpClient) throws IOException {
LOGGER.info("【删除文件】fileName : " + fileName);
baseValidate(ftpClient);
if (StringUtils.isBlank(fileName)) {
LOGGER.warn("【参数fileName为空】");
throw new NullArgumentException("fileName");
}
return ftpClient.deleteFile(fileName);
}

/**
* 存储文件
* @param file {@link File}
* @throws Exception
*/
public static void storeFile(File file, FTPClient ftpClient) throws Exception {
if (file == null) {
LOGGER.warn("【存储的文件为空】");
throw new RuntimeException("存储的文件为空");
}
LOGGER.info("【存储文件】file : " + file.getName());
baseValidate(ftpClient);

FileInputStream input = new FileInputStream(file);
ftpClient.storeFile(file.getName(), input);
input.close();
}

/**
* 存储文件
* @param inputStream {@link InputStream}
* @param fileName 文件名
* @throws Exception
*/
public static void storeFile(InputStream inputStream, String fileName, FTPClient ftpClient) throws Exception {
LOGGER.info("【存储文件】fileName = " + fileName);
if (inputStream == null) {
LOGGER.warn("【参数inputStream为空】");
throw new RuntimeException("存储的文件为空");
}
baseValidate(ftpClient);
ftpClient.storeFile(fileName, inputStream);
inputStream.close();
}

/**
* 下载文件到指定目录
* @param ftpFile 文件服务器上的文件地址
* @param dstFile 输出文件的路径和名称
* @throws Exception
*/
public static void downLoad(String ftpFile, String dstFile, FTPClient ftpClient) throws Exception {
LOGGER.info("【下载文件到指定目录】ftpFile = " + ftpFile + " , dstFile = " + dstFile);
if (StringUtils.isBlank(ftpFile)) {
LOGGER.warn("【参数ftpFile为空】");
throw new RuntimeException("【参数ftpFile为空】");
}
if (StringUtils.isBlank(dstFile)) {
LOGGER.warn("【参数dstFile为空】");
throw new RuntimeException("【参数dstFile为空】");
}
baseValidate(ftpClient);
File file = new File(dstFile);
FileOutputStream fos = new FileOutputStream(file);
ftpClient.retrieveFile(ftpFile, fos);
fos.flush();
fos.close();
}

/**
* 从文件服务器获取文件流
* @param ftpFile 文件服务器上的文件地址
* @return {@link InputStream}
* @throws IOException
*/
public static InputStream retrieveFileStream(String ftpFile, FTPClient ftpClient) throws IOException {
LOGGER.info("【从文件服务器获取文件流】ftpFile : " + ftpFile);
if (StringUtils.isBlank(ftpFile)) {
LOGGER.warn("【参数ftpFile为空】");
throw new RuntimeException("【参数ftpFile为空】");
}
baseValidate(ftpClient);
return ftpClient.retrieveFileStream(ftpFile);
}

/**
* 复制文件
* @param ftpClient {@link FTPClient}
* @param sourceFile 源文件
* @param targetDir 目标文件夹
* @return 复制后的文件路径及文件名
* @throws Exception
*/
public static String copy(FTPClient ftpClient, String sourceFile, String targetDir) throws Exception {
return copy(ftpClient, sourceFile, targetDir, FileUtil.getFileNameNoPath(sourceFile));
}

/**
* 复制文件
* @param ftpClient {@link FTPClient}
* @param sourceFile 源文件
* @param targetDir 目标文件夹
* @param newName 新的文件名
* @return 复制后的文件路径及文件名
* @throws Exception
*/
public static String copy(FTPClient ftpClient, String sourceFile, String targetDir, String newName)
throws Exception {
LOGGER.info("【拷贝文件】sourceFile = " + sourceFile + " , targetDir = " + targetDir + " , newName = " + newName);
if (StringUtils.isBlank(sourceFile)) {
LOGGER.warn("【参数sourceFile为空】");
throw new NullArgumentException("sourceFile");
}
if (StringUtils.isBlank(targetDir)) {
LOGGER.warn("【参数targetDir为空】");
throw new NullArgumentException("targetDir");
}
if (StringUtils.isBlank(newName)) {
LOGGER.warn("【参数newName为空】");
throw new NullArgumentException("newName");
}
baseValidate(ftpClient);
LOGGER.info("【从文件服务器读取源文件到输入流中】");
InputStream is = ftpClient.retrieveFileStream(sourceFile);
// 主动调用一次getReply()把接下来的226消费掉. 这样做是可以解决这个返回null问题
ftpClient.getReply();
if (is == null) {
LOGGER.warn("【未找到源文件】");
throw new RuntimeException("未找到源文件");
}
LOGGER.info("【将输入流存储到指定的目录】");
changeWorkingDirectory(targetDir, ftpClient);
changeWorkingDirectory(DateUtils.getNow(DateUtils.FORMAT_SHORT_FOLDER), ftpClient);
storeFile(is, newName, ftpClient);

return ftpClient.printWorkingDirectory() + File.separator + newName;
}

/**
* 基本校验
* @param ftpClient {@link FTPClient}
*/
private static void baseValidate(FTPClient ftpClient) {
if (ftpClient == null) {
LOGGER.warn("【参数ftpClient为空】");
throw new NullArgumentException("ftpClient");
}
}
}

FTPManager.java代码:

/**
*
*/
package com.common.file;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.annotation.Resource;

import org.apache.commons.lang.NullArgumentException;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import com.common.DateUtils;
import com.common.property.FileSystemProperties;

/**
* FTP文件管理器
* @author luolin
*
* @version $id:FTPManager.java,v 0.1 2015年11月16日 上午11:08:13 luolin Exp $
*/
@Component("ftpManager")
public class FTPManager {

private static final Logger  LOGGER = Logger.getLogger(FTPManager.class);
/** file.system.properties文件内容映射类 */
@Resource(name = "fileSystemProperties")
private FileSystemProperties fileSystemProperties;

/**
* 上传文件到FTP服务器
* @param file {@link File}
* @return 文件上传到服务器的地址
*/
public String upload(File file) {
LOGGER.info("【上传文件到FTP服务器】");
if (file == null) {
LOGGER.warn("【参数file为空】");
throw new NullArgumentException("file");
}

FTPClient ftpClient = connectServer(fileSystemProperties.getProjectWorkingDirectory());
// 切换到子目录,按日期,每天创建一个目录
String subFolder = DateUtils.getNow(DateUtils.FORMAT_SHORT_FOLDER);
FTPClientUtil.changeWorkingDirectory(subFolder, ftpClient);
try {
FTPClientUtil.upload(file, ftpClient);
} catch (Exception e) {
LOGGER.error("【文件上传失败】", e);
throw new RuntimeException("文件上传失败");
} finally {
FTPClientUtil.closeConnection(ftpClient);
}
String uploadedFilePath = fileSystemProperties.getProjectWorkingDirectory() + File.separator + subFolder
+ File.separator + file.getName();
LOGGER.info("【文件上传完成】uploadedFilePath = " + uploadedFilePath);
return uploadedFilePath;
}

/**
* 上传文件到FTP服务器
* @param file {@link File}
* @param targetFolder 目标子目录
* @return 文件上传到服务器的地址
*/
public String upload(File file, String targetFolder) {
LOGGER.info("【上传文件到FTP服务器】targetFolder : " + targetFolder);
if (file == null) {
LOGGER.warn("【参数file为空】");
throw new NullArgumentException("file");
}

FTPClient ftpClient = connectServer(fileSystemProperties.getProjectWorkingDirectory());
// 切换到子目录,按日期,每天创建一个目录
String subFolder = DateUtils.getNow(DateUtils.FORMAT_SHORT_FOLDER);
FTPClientUtil.changeWorkingDirectory(targetFolder, ftpClient);
FTPClientUtil.changeWorkingDirectory(subFolder, ftpClient);
try {
FTPClientUtil.upload(file, ftpClient);
} catch (Exception e) {
LOGGER.error("【文件上传失败】", e);
throw new RuntimeException("文件上传失败");
} finally {
FTPClientUtil.closeConnection(ftpClient);
}
String uploadedFilePath = fileSystemProperties.getProjectWorkingDirectory() + File.separator + targetFolder
+ File.separator + subFolder + File.separator + file.getName();
LOGGER.info("【文件上传完成】uploadedFilePath = " + uploadedFilePath);
return uploadedFilePath;
}

/**
* 连接服务器
* @return {@link FTPClient}
*/
private FTPClient connectServer(String workingDirectory) {
FTPClient ftpClient = null;
try {
// 连接服务器,并切换到对应的项目文件存储目录
ftpClient = FTPClientUtil.connect(fileSystemProperties.getHost(), fileSystemProperties.getPort(),
fileSystemProperties.getUsername(), fileSystemProperties.getPwd(), workingDirectory);
} catch (Exception e) {
LOGGER.error("【连接服务器失败】", e);
throw new RuntimeException("连接服务器失败");
}
return ftpClient;
}

/**
* 连接服务器
* @return {@link FTPClient}
*/
private FTPClient connectServer() {
FTPClient ftpClient = null;
try {
// 连接服务器,并切换到对应的项目文件存储目录
ftpClient = FTPClientUtil.connect(fileSystemProperties.getHost(), fileSystemProperties.getPort(),
fileSystemProperties.getUsername(), fileSystemProperties.getPwd());
} catch (Exception e) {
LOGGER.error("【连接服务器失败】", e);
throw new RuntimeException("连接服务器失败");
}
return ftpClient;
}

/**
* 从服务器获取文件输入流
* @param fileName 文件路径和名称
* @return {@link InputStream}
*/
public InputStream getFileInputStream(String fileName) {
LOGGER.info("【从服务器获取文件输入流】fileName = " + fileName);
if (StringUtils.isBlank(fileName)) {
LOGGER.warn("【参数fileName为空】");
throw new NullArgumentException("fileName");
}
FTPClient ftpClient = connectServer();
try {
return FTPClientUtil.retrieveFileStream(fileName, ftpClient);
} catch (IOException e) {
LOGGER.error("【获取文件流失败】", e);
throw new RuntimeException("获取文件流失败");
} finally {
FTPClientUtil.closeConnection(ftpClient);
}
}

/**
* 从文件服务器文件下载到应用服务器本地
* @param fileName 文件路径及名称
* @param tmpPath 临时文件存放目录
* @return 存储到临时文件目录的完整路径
*/
public String downloadFileToLocal(String fileName, String tmpPath) {
LOGGER.info("【从文件服务器文件下载到应用服务器本地】fileName = " + fileName);
if (StringUtils.isBlank(fileName)) {
LOGGER.warn("【参数fileName为空】");
throw new NullArgumentException("fileName");
}
FTPClient ftpClient = connectServer();
String name = FileUtil.getFileNameNoPath(fileName);
try {
FTPClientUtil.downLoad(fileName, tmpPath + File.separator + name, ftpClient);
} catch (Exception e) {
LOGGER.error("【下载文件失败】", e);
throw new RuntimeException("下载文件失败");
} finally {
FTPClientUtil.closeConnection(ftpClient);
}
return tmpPath + File.separator + name;
}

/**
* 删除文件服务器的文件
* @param fileName 文件在文件服务器的地址
* @throws IOException
*/
public void delete(String fileName) throws IOException {
LOGGER.info("【删除文件服务器的文件】fileName = " + fileName);
FTPClientUtil.delete(fileName, connectServer());
}

/**
* 文件拷贝
* @param sourceFile 源文件地址
* @param targetDir 目标文件夹
* @return 文件拷贝后的完整路径
*/
public String copy(String sourceFile, String targetDir) {
LOGGER.info("【文件拷贝】sourceFile = " + sourceFile + " , targetDir = " + targetDir);
if (StringUtils.isBlank(sourceFile)) {
LOGGER.warn("【参数sourceFile为空】");
throw new NullArgumentException("sourceFile");
}
if (StringUtils.isBlank(targetDir)) {
LOGGER.warn("【参数targetDir为空】");
throw new NullArgumentException("targetDir");
}
try {
return FTPClientUtil.copy(connectServer(), sourceFile, fileSystemProperties.getProjectWorkingDirectory()
+ File.separator + targetDir);
} catch (Exception e) {
LOGGER.error("【文件拷贝失败】", e);
throw new RuntimeException("文件拷贝失败");
}
}
}

下面也给出我测试的时候,写的demo的代码

/**
*
*/
package com.eay.ftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

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

/**
* FTP客户端工具类示例
* @author ll
*
* @version $id:FTPClientExample.java,v 0.1 2015年11月13日 上午11:32:24 ll Exp $
*/
public class FTPClientExample {

/** FTP客户端实例 */
private FTPClient ftpClient;

/**
* 私有构造器
*/
private FTPClientExample() {
}

/**
* 内部类维护单例,防止并发问题
* @author luolin
*
* @version $id:FTPClientExample.java,v 0.1 2015年11月13日 下午2:34:08 luolin Exp $
*/
private static class SingletonFactory {
private static FTPClientExample instance = new FTPClientExample();
}

/**
* 获取实例
* @return {@link FTPClientExample}
*/
public static FTPClientExample getInstance() {
return SingletonFactory.instance;
}

/**
* 连接文件服务器
* @param addr 文件服务器地址
* @param port 端口
* @param username 用户名
* @param password 密码
* @throws Exception
*/
public void connect(String addr, int port, String username, String password) throws Exception {
ftpClient = new FTPClient();
// 连接
ftpClient.connect(addr, port);
// 登录
ftpClient.login(username, password);
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
// 判断文件服务器是否可用??
if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
ftpClient.disconnect();
}
}

/**
* 连接文件服务器
* @param addr 文件服务器地址
* @param port 端口
* @param username 用户名
* @param password 密码
* @param workingDirectory 目标连接工作目录
* @throws Exception
*/
public void connect(String addr, int port, String username, String password, String workingDirectory)
throws Exception {
ftpClient = new FTPClient();
// 连接
ftpClient.connect(addr, port);
// 登录
ftpClient.login(username, password);
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
// 判断文件服务器是否可用??
if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
ftpClient.disconnect();
}
changeWorkingDirectory(workingDirectory);
}

/**
* 关闭连接,使用完连接之后,一定要关闭连接,否则服务器会抛出 Connection reset by peer的错误
* @throws IOException
*/
public void closeConnection() throws IOException {
ftpClient.disconnect();
}

/**
* 切换工作目录
* @param directory 目标工作目录
* @throws IOException
*/
public void changeWorkingDirectory(String directory) throws IOException {
// 切换到目标工作目录
if (!ftpClient.changeWorkingDirectory(directory)) {
ftpClient.makeDirectory(directory);
ftpClient.changeWorkingDirectory(directory);
}
}

/**
* @param file 上传的文件或文件夹
* @throws Exception
*/
public void upload(File file) throws Exception {

if (file == null) {
throw new RuntimeException("上传文件为空");
}
// 是文件,直接上传
if (!file.isDirectory()) {
storeFile(new File(file.getPath()));
return;
}

ftpClient.makeDirectory(file.getName());
ftpClient.changeWorkingDirectory(file.getName());
// 文件夹,递归上传所有文件
for (File item : file.listFiles()) {
if (!item.isDirectory()) {
storeFile(item);
continue;
}
upload(item);
ftpClient.changeToParentDirectory();
}
}

/**
* 删除文件
* @param fileName 要删除的文件地址
* @return true/false
* @throws Exception
*/
public boolean delete(String fileName) throws Exception {
return ftpClient.deleteFile(fileName);
}

/**
* 存储文件
* @param file {@link File}
* @throws Exception
*/
private void storeFile(File file) throws Exception {
FileInputStream input = new FileInputStream(file);
ftpClient.storeFile(file.getName(), input);
input.close();
}

/**
* 下载文件
* @param ftpFile 文件服务器上的文件地址
* @param dstFile 输出文件的路径和名称
* @throws Exception
*/
public void downLoad(String ftpFile, String dstFile) throws Exception {
File file = new File(dstFile);
FileOutputStream fos = new FileOutputStream(file);
ftpClient.retrieveFile(ftpFile, fos);
fos.flush();
fos.close();
}

/**
* 从文件服务器获取文件流
* @param ftpFile 文件服务器上的文件地址
* @return {@link InputStream}
* @throws IOException
*/
public InputStream retrieveFileStream(String ftpFile) throws IOException {
return ftpClient.retrieveFileStream(ftpFile);
}

public static void main(String[] args) throws Exception {
FTPClientExample emp = FTPClientExample.getInstance();
String addr = "192.168.111.60";
int port = 21;
String username = "admin";
String password = "admin";
emp.connect(addr, port, username, password);

// 上传文件
emp.changeWorkingDirectory("bss");
emp.upload(new File("E:\\example.txt"));
// 下载文件到指定目录
//        emp.downLoad("bss\\example.txt", "E:\\example2.txt");

// 删除文件
//        emp.delete("bss\\example.txt");

// 关闭连接,防止文件服务器抛出 Connection reset by peer的错误
emp.closeConnection();

}
}

<!--ftp -->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
</dependency>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息