Skip to content

feilong net filetransfer

feilong edited this page Sep 17, 2020 · 10 revisions

Welcome to feilong-net-filetransfer

文件传输工具库,支持ftp,sftp传输文件

License jar size 19K

1.简介:

文件传输,是开发中常见的功能,经常会接到需求,

把xxx报表自动上传到某个ftp/sftp目录

市面上流传的工具类,有以下缺点:

  1. 比较分散孤立(通常如果我们要使用ftp功能会选择commons-net,使用sftp功能会选择jsch,但是会写两套代码,两者之间没有任何关系)
  2. 参数硬编码在java 类里面

这些缺点,不利于做 ftpsftp 的快速切换(品牌某天说我们现在不用ftp了,使用sftp,我们不得不大量的修改代码),以及修改参数配置

feilong-net-filetransfer 可以做到快速切换这一点,只需要简单的配置,简单的调用API,可以大幅度减少开发工作量就可以完成工作

2.feilong-net-filetransfer 特点:

  1. 支持快速切换 ftp和sftp模式

  2. 支持Spring DI 配置参数

  3. 有完备详细的log输出

    open

  4. 支持常用功能,API简单易懂

    1. 上传

      1. 单个文件上传
      2. 整个文件夹上传
      3. 多个不定路径文件上传
      4. 多个不定路径文件夹上传
    2. 下载

      1. 单个文件下载
      2. 整个文件夹下载
      3. 多个不定路径文件下载
      4. 多个不定路径文件夹下载
    3. 删除(注:不支持删除 / 根路径)

      1. 单个文件删除
      2. 整个文件夹删除
      3. 多个不定路径文件删除
      4. 多个不定路径文件夹删除

3.:dragon: Maven使用配置

<dependency>
    <groupId>com.github.ifeilong</groupId>
    <artifactId>feilong</artifactId>
    <version>3.0.10</version>
</dependency>

其次, 使用 SFTP 功能 .com.feilong.net.filetransfer.sftp.SFTPFileTransfer

需自行依赖

<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.55</version>
</dependency>

使用 FTP 功能 .com.feilong.net.filetransfer.sftp.SFTPFileTransfer

4.SFTP 使用篇

sftp是Secure File Transfer Protocol的缩写,安全文件传送协议。可以为传输文件提供一种安全的加密方法

如果你要使用 sftp 传输,那么我们需要进行以下 4 步即可

4.1 step1.准备2个参数配置文件

fileTransfer-sftp.properties (用于sftp) ​

fileTransfer.sftp.hostName=*******
fileTransfer.sftp.userName=*******
fileTransfer.sftp.password=*******
 
fileTransfer.sftp.port=22
 
#默认0
fileTransfer.sftp.sessionTimeout=0

fileTransfer-sftp-sshConfig.properties (sftp 可以配置session 参数信息)

StrictHostKeyChecking=no

4.2 step2, 准备spring-fileTransfer.xml

注意:需要自行处理文件分不同环境的问题

<util:properties id="p_sftp" location="classpath:config/fileTransfer-sftp.properties"></util:properties>
 
<util:properties id="p_sftp-sshConfig" location="classpath:config/fileTransfer-sftp-sshConfig.properties"></util:properties>
 
<!-- sftp -->
<bean id="sftpFileTransfer" class="com.feilong.net.filetransfer.sftp.SFTPFileTransfer" scope="prototype">
	<property name="sftpFileTransferConfig">
		<bean class="com.feilong.net.filetransfer.sftp.SFTPFileTransferConfig">
			<property name="hostName" value="#{p_sftp['fileTransfer.sftp.hostName']}" />
			<property name="userName" value="#{p_sftp['fileTransfer.sftp.userName']}" />
			<property name="password">
				<value><![CDATA[#{p_sftp['fileTransfer.sftp.password']}]]></value>
			</property>
			<property name="port" value="#{p_sftp['fileTransfer.sftp.port']}" />

			<property name="sessionTimeout" value="#{p_sftp['fileTransfer.sftp.sessionTimeout']}" />
			<property name="sshConfig" ref="p_sftp-sshConfig" />
		</bean>
	</property>
</bean>

4.3 step3.代码中引用配置的bean

可以使用 @Qualifier来精确指定bean ​

@Autowired
@Qualifier("sftpFileTransfer")
private FileTransfer        fileTransfer;

4.4 step4 调用API

private final String        remoteDirectory = "/home/feilong/test/20160616/201606160101";
@Test
public void upload() throws Exception{
    String singleLocalFileFullPath = "E:\\1.txt";
    fileTransfer.upload(remoteDirectory, singleLocalFileFullPath);
}

5. FTP 使用篇

FTP(File Transfer Protocol, FTP)TCP/IP 网络上两台计算机传送文件的协议,FTP是在TCP/IP网络和INTERNET上最早使用的协议之一,它属于网络协议组的应用层.

如果你要使用 ftp 传输,那么我们需要进行以下 4 步即可

5.1 step1.准备1个参数配置文件

fileTransfer-ftp.properties (用于ftp) ​

fileTransfer.ftp.hostName=********
fileTransfer.ftp.userName=********
fileTransfer.ftp.password=********
 
#可以解决 FTPClientlistNames方法得到当前目录下所有文件的列表. 中文文件名是乱码.
fileTransfer.ftp.FTPClient.controlEncoding=gbk
fileTransfer.ftp.FTPClient.defaultPort=21
fileTransfer.ftp.FTPClient.dataTimeout=120000

5.2 step2, 准备spring-fileTransfer.xml

**注意:**需要自行处理文件分不同环境的问题

<util:properties id="p_ftp" location="classpath:config/fileTransfer-ftp.properties"></util:properties>
 
<!-- ftp -->
<bean id="ftpFileTransfer" class="com.feilong.net.filetransfer.ftp.FTPFileTransfer" scope="prototype">
	<property name="ftpFileTransferConfig">
		<bean class="com.feilong.net.filetransfer.ftp.FTPFileTransferConfig">
			<property name="hostName" value="#{p_ftp['ftpFileTransfer.ftp.hostName']}" />
			<property name="userName" value="#{p_ftp['ftpFileTransfer.ftp.userName']}" />
			<property name="password">
				<value><![CDATA[#{p_ftp['ftpFileTransfer.ftp.password']}]]></value>
			</property>
		</bean>
	</property>

	<property name="ftpClient">
		<!-- FTPClient -->
		<bean class="org.apache.commons.net.ftp.FTPClient">
			<property name="controlEncoding" value="#{p_ftp['ftpFileTransfer.ftp.FTPClient.controlEncoding']}" />
			<property name="defaultPort" value="#{p_ftp['ftpFileTransfer.ftp.FTPClient.defaultPort']}" />
			<property name="dataTimeout" value="#{p_ftp['ftpFileTransfer.ftp.FTPClient.dataTimeout']}" />
		</bean>
	</property>
</bean>
		 

5.3 step3.代码中引用配置的bean

使用 @Qualifier来精确指定bean ​

@Autowired
@Qualifier("ftpFileTransfer")
private FileTransfer        fileTransfer;

5.4 step4 调用API

@Override
@Test
public void deleteDirEmpty() throws Exception{
    String remoteAbsolutePath = "/webstore/InlineSales_Test/a/";
    fileTransfer.delete(remoteAbsolutePath);
}

@Override
@Test
public void deleteNotExist() throws Exception{
    String remoteAbsolutePath = "/webstore/InlineSales_Test/2011-07-051/";
    fileTransfer.delete(remoteAbsolutePath);
}

6 切换 ftp和sftp

以后如果需要 ftp 切换到 sftp,仅需要更换 @Qualifier 值以及目录参数 就可以了

7 多线程或者多个job

多线程或者多job同时跑的情况

spring xml 配置一定要加上 scope="prototype"

具体参见 https://github.com/venusdrogon/feilong-platform/issues/22

8 关于 FileTransfer api

该接口,提供四个方法

open

具体可以参见 类的 javadoc

//-----------------------------下载-----------------------------------------------------

/**
 * 打开一次链接,将一批远程文件/文件夹 (<code>remotePaths</code>)循环下载到本地目录 <code>localAbsoluteDirectoryPath</code>.
 *
 * <h3>说明:</h3>
 * <blockquote>
 * <ol>
 * <li>如果 <code>localAbsoluteDirectoryPath</code>本地目录地址不存在,会自动<b>级联创建</b></li>
 * <li>如果 <code>remotePaths</code>里面有文件是个文件(file),会将此文件直接下载到 <code>localAbsoluteDirectoryPath</code> 目录下面</li>
 * <li>
 * 如果 <code>remotePaths</code>里面有文件是个文件夹(Directory),会先在 <b>localAbsoluteDirectoryPath</b> 下面创建同名文件夹,再<b>递归下载</b>文件(相当于整个文件夹下载下来)
 * </li>
 * <li>如果 <code>localAbsoluteDirectoryPath</code> 目录下面已经存在和<code>remotePaths</code>里面同名的文件,那么会<b>下载覆盖</b></li>
 * </ol>
 * </blockquote>
 *
 * <h3>示例:</h3>
 *
 * <blockquote>
 *
 * <pre class="code">
 * String[] remotePaths = {
 *                          "/upload/Inbound/InventoryAdjustments/Archive/2016-07-15_11-58-58.389-INVENTORY_ADJUSTMENTS_3PL_20160715-154626-073.XML",
 *                          "/upload/Inbound/InventoryAdjustments/Archive/2016-07-22_10-46-00.318-INVENTORY_ADJUSTMENTS_3PL_20160722-144626-073.XML" };
 * String localAbsoluteDirectoryPath = "E:\\test\\1";
 * fileTransfer.download(localAbsoluteDirectoryPath, remotePaths);
 * </pre>
 *
 * </blockquote>
 *
 * @param localAbsoluteDirectoryPath
 *            本地绝对的目录<br>
 *            如果不存在,支持级联创建 <br>
 *            如果 <code>localAbsoluteDirectoryPath</code> 是null,抛出 {@link NullPointerException}<br>
 *            如果 <code>localAbsoluteDirectoryPath</code> 是blank,抛出 {@link IllegalArgumentException}<br>
 * @param remotePaths
 *            一批远程文件远程路径,<br>
 *            可以是文件,也可以文件夹 <br>
 *            如果 <code>remotePaths</code> 是null,抛出 {@link NullPointerException}<br>
 *            如果 <code>remotePaths</code> 是empty,抛出 {@link IllegalArgumentException}<br>
 *            任意一个值 null或者empty, {@link IllegalArgumentException}
 */
void download(String localAbsoluteDirectoryPath,String...remotePaths);

//-----------------------------上传-----------------------------------------------------
/**
 * 支持将多个不定路径文件 <code>batchLocalFileFullPaths</code> 上传到远程文件夹 <code>remoteDirectory</code>.
 *
 * <pre class="code">
 *
 * String[] batchLocalFileFullPaths = { "E:\\test", "E:\\1.jpg" };
 *
 * String remoteDirectory = "/webstore/InlineSales_Test/2011-07-05/";
 * </pre>
 *
 * <h3>说明:</h3>
 * <blockquote>
 * <ol>
 * <li>如果 localFileFullPath 是个文件(file), 会将此文件直接上传到 remoteDirectory 目录下面</li>
 * <li>如果 localFileFullPath 是个文件夹(Directory), 首先会先在 remoteDirectory 下面创建同名文件夹,并<b>递归上传</b>文件(相当于整个文件夹上传)</li>
 * <li>新的文件的名称和你上传文件的名称一样的,也就是,你传的什么名称文件/文件夹到服务器就是什么名称文件/文件夹</li>
 * </ol>
 * </blockquote>
 *
 * @param remoteDirectory
 *            远程文件夹名称,你要传到哪个文件夹下面
 * @param batchLocalFileFullPaths
 *            上传的文件名(数组),全路径 <br>
 *            不能为 null或者empty,否则 {@link IllegalArgumentException}<br>
 *            任意一个值 null或者empty, {@link IllegalArgumentException}<br>
 *            任意一个值localFileFullPath文件不存在, {@link IllegalArgumentException}
 * @return 全部成功返回true,否则一旦有失败则返回false<br>
 *         如果 <code>remoteDirectory</code> 是null,抛出 {@link NullPointerException}<br>
 *         如果 <code>remoteDirectory</code> 是blank,抛出 {@link IllegalArgumentException}<br>
 */
boolean upload(String remoteDirectory,String...batchLocalFileFullPaths);

//-----------------------------删除-----------------------------------------------------
/**
 * 删除远程的一组文件 <code>remoteAbsolutePaths</code>.
 *
 * <pre class="code">
 *
 * String[] remoteAbsolutePaths = { "/webstore/InlineSales_Test/2011-07-05/test", "/webstore/InlineSales_Test/2011-07-05/1.cvs" };
 * </pre>
 *
 * <h3>说明:</h3>
 * <blockquote>
 * <ol>
 * <li>不管是windows还是linux、unix,都不能在同一目录结构下创建同名的文件夹和文件</li>
 * <li>如果 remoteAbsolutePath 是个文件(file), 会将此文件直接删除</li>
 * <li>如果 remoteAbsolutePath 是个文件夹(Directory),首先<b>递归删除</b>该文件夹下面 所有的文件/文件夹再删除此文件夹</li>
 * <li>不支持删除 '/'根目录 (危险)</li>
 * </ol>
 * </blockquote>
 *
 * @param remoteAbsolutePaths
 *            一组文件,绝对路径 <br>
 *            不能为 null或者empty,否则 {@link IllegalArgumentException}<br>
 *            任意一个值 null或者empty, {@link IllegalArgumentException}<br>
 *            任意一个值= / , {@link IllegalArgumentException} 危险!!
 * @return 删除成功返回true,否则false<br>
 *         不支持 删除全部 危险<br>
 *         一旦有一个文件 null或者empty抛错
 */
boolean delete(String...remoteAbsolutePaths);

//----------------------------读取-----------------------------------------------------
/**
 * 获得某特定文件夹下面指定文件名相关信息.
 *
 * @param remotePath
 *            远程地址
 * @param fileNames
 *            文件名称组
 * @return 如果fileNames 有文件不在 remotePath 路径下面, 则返回的map中这条数据的value 是null
 */
Map<String, FileInfoEntity> getFileEntityMap(String remotePath,String...fileNames);

9. UML类图(class-diagram)

open

10. 参考

core

Clone this wiki locally