-
Notifications
You must be signed in to change notification settings - Fork 30
feilong net filetransfer
文件传输工具库,支持ftp,sftp传输文件
文件传输,是开发中常见的功能,经常会接到需求,
把xxx报表自动上传到某个ftp/sftp目录
市面上流传的工具类,有以下缺点:
- 比较分散孤立(通常如果我们要使用ftp功能会选择
commons-net
,使用sftp功能会选择jsch
,但是会写两套代码,两者之间没有任何关系) - 参数硬编码在java 类里面
这些缺点,不利于做 ftp
和 sftp
的快速切换(品牌某天说我们现在不用ftp了,使用sftp,我们不得不大量的修改代码),以及修改参数配置
而 feilong-net-filetransfer
可以做到快速切换这一点,只需要简单的配置
,简单的调用API
,可以大幅度减少开发工作量就可以完成工作
-
支持快速切换 ftp和sftp模式
-
支持
Spring DI
配置参数 -
有完备详细的log输出
-
支持常用功能,API简单易懂
-
上传
-
单个文件
上传 -
整个文件夹
上传 -
多个不定路径文件
上传 -
多个不定路径文件夹
上传
-
-
下载
-
单个文件
下载 -
整个文件夹
下载 -
多个不定路径文件
下载 -
多个不定路径文件夹
下载
-
-
删除(注:不支持删除 / 根路径)
-
单个文件
删除 -
整个文件夹
删除 -
多个不定路径文件
删除 -
多个不定路径文件夹
删除
-
-
<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
sftp是
Secure File Transfer Protocol
的缩写,安全文件传送协议。可以为传输文件提供一种安全的加密方法
如果你要使用 sftp
传输,那么我们需要进行以下 4 步
即可
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
注意:需要自行处理文件分不同环境
的问题
<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>
可以使用 @Qualifier
来精确指定bean
@Autowired
@Qualifier("sftpFileTransfer")
private FileTransfer fileTransfer;
private final String remoteDirectory = "/home/feilong/test/20160616/201606160101";
@Test
public void upload() throws Exception{
String singleLocalFileFullPath = "E:\\1.txt";
fileTransfer.upload(remoteDirectory, singleLocalFileFullPath);
}
FTP(File Transfer Protocol, FTP)
是TCP/IP
网络上两台计算机传送文件的协议,FTP是在TCP/IP网络和INTERNET上最早使用的协议之一,它属于网络协议组的应用层.
如果你要使用 ftp 传输,那么我们需要进行以下 4 步
即可
fileTransfer-ftp.properties (用于ftp)
fileTransfer.ftp.hostName=********
fileTransfer.ftp.userName=********
fileTransfer.ftp.password=********
#可以解决 FTPClient的listNames方法得到当前目录下所有文件的列表. 中文文件名是乱码.
fileTransfer.ftp.FTPClient.controlEncoding=gbk
fileTransfer.ftp.FTPClient.defaultPort=21
fileTransfer.ftp.FTPClient.dataTimeout=120000
**注意:**需要自行处理文件分不同环境
的问题
<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>
使用 @Qualifier
来精确指定bean
@Autowired
@Qualifier("ftpFileTransfer")
private FileTransfer fileTransfer;
@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);
}
以后如果需要 ftp
切换到 sftp
,仅需要更换 @Qualifier
值以及目录参数
就可以了
多线程或者多job同时跑的情况
spring xml 配置一定要加上 scope="prototype"
具体参见 https://github.com/venusdrogon/feilong-platform/issues/22
该接口,提供四个方法
具体可以参见 类的 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);
core