FTP上传文件,Apache篇

2022-05-07 15:25:06 浏览数 (1)

        前段时间做了个任务,是公司liunx机器上有个公司静态网站的文件夹,因为不定期的修改,修改完之后要同步到FTP服务器上,之前一直是手动使用FTP工具来同步,我的任务是开发一个能够同步静态网站的action,集成到ETL工具中,然后每天会自动运行这个action,这样就避免手动同步了。

        之前没有做过FTP上传,百度之,做FTP上传有两个类库,一个sun的FtpClient,不过sun是不推荐使用这个类库的,而且引入的时候要指定rule,另一个是Apache的FTPClient,我先使用了sun的,出现了一些问题,没有找到解决方案,本文主要说明的是使用Apache的工具类,关于sun的FtpClient,会在下一篇文章中说明。

        其实主要就是干4个事情:

        1. 初始化参数

        2. 连接ftp

        3. 拷贝文件,有可能是递归,因为文件夹下包含目录

        4. 断开ftp连接

        每次同步只是同步更新文件,所以我把同步时间记录在一个文件里,放在本地,上传文件的时候判断该文件的更新时间是否大于上次的同步时间。

还有就是FTPClient的storeFile()方法,需要两个参数,一个是文件名,另一个是输入流,这样我就无法控制它的缓冲区大小,拷入源码追踪了一个,它的缓冲区字节是在Utils中定义的,默认是1024,我给它改成了1024 × 64的,然后重新编译回去。

        还有一个方法是storeFileStream()方法,它会返回一个OutputStream,不过如果该文件不存在的话,返回的是null,我没有找到创建文件的方式,很遗憾。

        下面贴代码,主要看copyDirectory方法。

代码语言:javascript复制
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

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

/**
 * 向ftp同步静态网站(ftp上传)
 * @author gaoshuang
 *
 */
public class SynchronizeWebsiteAction implements IETLAction {
	/**
	 * 同步文件计数
	 */
	private int num;
	/**
	 * 本地文件路径
	 */
	private String localPath;
	/**
	 * ftp地址
	 */
	private String ipAdress;
	/**
	 * 用户名
	 */
	private String username;
	/**
	 * 密码
	 */
	private String password;
	/**
	 * ftp文件路径
	 */
	private String ftpPath;
	/**
	 * 上次更新时间
	 */
	private long lastUpdate;
	/**
	 * ftp连接
	 */
	private FTPClient ftp;
	
	public void addAdapter(String name, int type, ISourceAdapter adapter,
			String description) {
	}
	
	/**
	 * 入口方法
	 */
	public void execute(String params, ETLContext context) throws Exception {
		init(params);
		connect();
		copyDirectory(localPath, ftpPath);
		disConnect();
		// 记录本次更新时间
		OutputStream os = new FileOutputStream(localPath   "/lastUpdate.txt");
		os.write((System.currentTimeMillis()   "").getBytes());
	}
	
	/**
	 * 初始化
	 * @param params action参数
	 * @throws NumberFormatException
	 * @throws IOException
	 */
	private void init(String params) throws NumberFormatException, IOException {
		String[] paths = params.split(",");
		localPath = paths[0];
		String[] ftpInfo = paths[1].split(";");
		ipAdress = ftpInfo[0];
		username = ftpInfo[1];
		password = ftpInfo[2];
		ftpPath = ftpInfo[3];
		lastUpdate = getLastUpdate();
	}
	
	/**
	 * 得到上次更新时间
	 * @return
	 * @throws NumberFormatException
	 * @throws IOException
	 */
	private long getLastUpdate() throws NumberFormatException, IOException {
		File file = new File(localPath   "/lastUpdate.txt");
		long time = 0;
		if(file.exists()) {
			BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
			time = Long.parseLong(br.readLine());
		}
		return time;
	}

	/**
	 * 拷贝目录
	 * @param srcDirectoryPath 源
	 * @param destDirectoryPath 目标
	 * @throws IOException 
	 */
	public void copyDirectory(String srcDirectoryPath, String destDirectoryPath) throws IOException {
		// 创建不存在的目录
		reConnect();
		ftp.makeDirectory(destDirectoryPath);
		File src = new File(srcDirectoryPath);
		File[] allFile = src.listFiles(); // 取得当前文件夹下的所有文件,包括目录
		String srcName = "";
		// 拷貝文件
		for (int currentFile = 0; currentFile < allFile.length; currentFile  ) {
			if (!allFile[currentFile].isDirectory()) {
				// 如果是文件是采用处理文件的方式
				srcName = allFile[currentFile].toString();
				Logger.debug("开始上传文件到"   destDirectoryPath   "/"   allFile[currentFile].getName());
				copyFile(srcName, destDirectoryPath, allFile[currentFile].getName());
			} else {
				// 如果是目录就采用递归处理
				Logger.debug(destDirectoryPath   "/"   allFile[currentFile].getName().toString());
				copyDirectory(allFile[currentFile].getPath().toString(), destDirectoryPath   "/"   allFile[currentFile].getName().toString()); 
			}
		}
	}
	
	/**
	 * 连接失去的时候重新连接
	 * @throws IOException
	 */
	private void reConnect() throws IOException {
		while(!ftp.isConnected()) {
			connect();
		}
	}

	/**
	 * 拷贝文件
	 * @param src
	 * @param dest
	 * @throws IOException 
	 */
	private void copyFile(String src, String dirPath, String fileName) throws IOException{
		File file = new File(src);
		if(file.lastModified() > lastUpdate && file.length() != 0) {
			reConnect();
			InputStream is = new FileInputStream(file);
			ftp.setControlEncoding("GBK");
			ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
			ftp.changeWorkingDirectory(dirPath);
			ftp.storeFile(fileName, is);
			is.close();
			Logger.debug("上传文件到"   ""   dirPath   "/"   fileName   "成功,这是第"     num   "个");
		}
	}
	
	/**
	 * 连接ftp服务器
	 * @throws IOException 
	 */
	private void connect() throws IOException {
		ftp = new FTPClient();
		ftp.connect(ipAdress);
		ftp.login(username, password);
	}
	
	/**
	 * 关闭连接
	 * @param ftp
	 * @throws IOException
	 */
	private void disConnect() throws IOException {
		ftp.disconnect();
	}
}

        可以发现,我没有做断点续传的功能,这也是程序中的一个缺陷,我会尽快完善,谢谢,发现代码有可改进之处,欢迎指出。

0 人点赞