转载:http://blog.csdn.net/lee272616/article/details/52789018

java远程操作文件服务器(linux),使用sftp协议
版本会持续更新,
当前版本:0.31
版本更新时间:2016-10-13
版本修正说明:
1.修正连接关闭,将关闭的方法改成私有,不允许使用者自行关闭(否则会导致连接池获取错误)

2.优化删除文件及文件夹,先判断文件或文件夹是否存在,然后再删除

前言:

sftp是Secure File Transfer Protocol的缩写,安全文件传送协议。可以为传输文件提供一种安全的加密方法。sftp 与 ftp 有着几乎一样的语法和功能。SFTP 为 SSH的一部分,是一种传输档案至 Blogger 伺服器的安全方式。其实在SSH软件包中,已经包含了一个叫作SFTP(Secure File Transfer Protocol)的安全文件传输子系统,SFTP本身没有单独的守护进程,它必须使用sshd守护进程(端口号默认是22)来完成相应的连接操作,所以从某种意义上来说,SFTP并不像一个服务器程序,而更像是一个客户端程序。SFTP同样是使用加密传输认证信息和传输的数据,所以,使用SFTP是非常安全的。但是,由于这种传输方式使用了加密/解密技术,所以传输效率比普通的FTP要低得多,如果您对网络安全性要求更高时,可以使用SFTP代替FTP。

本工具基于对JSch - Java Secure Channel进行的封装,linux服务器不用安装任何插件和软件

使用指南:

首先是jar包

[html] view plaincopy
  1. <dependency>
  2. <groupId>com.jcraft</groupId>
  3. <artifactId>jsch</artifactId>
  4. <version>0.1.42</version>
  5. </dependency>

Sftp协议工具类-v0.1

[java] view plaincopy
  1. package com.noryar.filesystem.utils;
  2. import java.io.ByteArrayOutputStream;
  3. import java.io.File;
  4. import java.io.FileOutputStream;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. import java.util.Properties;
  8. import java.util.Vector;
  9. import org.apache.commons.lang.StringUtils;
  10. import com.jcraft.jsch.Channel;
  11. import com.jcraft.jsch.ChannelSftp;
  12. import com.jcraft.jsch.JSch;
  13. import com.jcraft.jsch.JSchException;
  14. import com.jcraft.jsch.Session;
  15. import com.jcraft.jsch.SftpException;
  16. /**
  17. * 文件工具类.
  18. * @author Leon Lee
  19. */
  20. public class SftpUtil {
  21. /**
  22. * 文件路径前缀. /ddit-remote
  23. */
  24. private static final String PRE_FIX = "/test-noryar";
  25. /**
  26. * 获取sftp协议连接.
  27. * @param host 主机名
  28. * @param port 端口
  29. * @param username 用户名
  30. * @param password 密码
  31. * @return 连接对象
  32. * @throws JSchException 异常
  33. */
  34. public static ChannelSftp getSftpConnect(final String host, final int port, final String username,
  35. final String password) throws JSchException {
  36. ChannelSftp sftp = null;
  37. JSch jsch = new JSch();
  38. jsch.getSession(username, host, port);
  39. Session sshSession = jsch.getSession(username, host, port);
  40. sshSession.setPassword(password);
  41. Properties sshConfig = new Properties();
  42. sshConfig.put("StrictHostKeyChecking", "no");
  43. sshSession.setConfig(sshConfig);
  44. sshSession.connect();
  45. Channel channel = sshSession.openChannel("sftp");
  46. channel.connect();
  47. sftp = (ChannelSftp) channel;
  48. return sftp;
  49. }
  50. /**
  51. * 下载文件-sftp协议.
  52. * @param downloadFile 下载的文件
  53. * @param saveFile 存在本地的路径
  54. * @param sftp sftp连接
  55. * @return 文件
  56. * @throws Exception 异常
  57. */
  58. public static File download(final String downloadFile, final String saveFile, final ChannelSftp sftp)
  59. throws Exception {
  60. FileOutputStream os = null;
  61. File file = new File(saveFile);
  62. try {
  63. if (!file.exists()) {
  64. File parentFile = file.getParentFile();
  65. if (!parentFile.exists()) {
  66. parentFile.mkdirs();
  67. }
  68. file.createNewFile();
  69. }
  70. os = new FileOutputStream(file);
  71. List<String> list = formatPath(downloadFile);
  72. sftp.get(list.get(0) + list.get(1), os);
  73. } catch (Exception e) {
  74. exit(sftp);
  75. throw e;
  76. } finally {
  77. os.close();
  78. }
  79. return file;
  80. }
  81. /**
  82. * 下载文件-sftp协议.
  83. * @param downloadFile 下载的文件
  84. * @param saveFile 存在本地的路径
  85. * @param sftp sftp连接
  86. * @return 文件 byte[]
  87. * @throws Exception 异常
  88. */
  89. public static byte[] downloadAsByte(final String downloadFile, final ChannelSftp sftp) throws Exception {
  90. ByteArrayOutputStream os = new ByteArrayOutputStream();
  91. try {
  92. List<String> list = formatPath(downloadFile);
  93. sftp.get(list.get(0) + list.get(1), os);
  94. } catch (Exception e) {
  95. exit(sftp);
  96. throw e;
  97. } finally {
  98. os.close();
  99. }
  100. return os.toByteArray();
  101. }
  102. /**
  103. * 删除文件-sftp协议.
  104. * @param deleteFile 要删除的文件
  105. * @param sftp sftp连接
  106. * @throws Exception 异常
  107. */
  108. public static void rmFile(final String deleteFile, final ChannelSftp sftp) throws Exception {
  109. try {
  110. sftp.rm(deleteFile);
  111. } catch (Exception e) {
  112. exit(sftp);
  113. throw e;
  114. }
  115. }
  116. /**
  117. * 删除文件夹-sftp协议.
  118. * @param deleteFile 文件夹路径
  119. * @param sftp sftp连接
  120. * @throws Exception 异常
  121. */
  122. public static void rmDir(final String pathString, final ChannelSftp sftp) throws Exception {
  123. try {
  124. sftp.rmdir(pathString);
  125. } catch (Exception e) {
  126. exit(sftp);
  127. throw e;
  128. }
  129. }
  130. /**
  131. * 上传文件-sftp协议.
  132. * @param srcFile 源文件
  133. * @param dir 保存路径
  134. * @param fileName 保存文件名
  135. * @param sftp sftp连接
  136. * @throws Exception 异常
  137. */
  138. private static void uploadFile(final String srcFile, final String dir, final String fileName, final ChannelSftp sftp)
  139. throws Exception {
  140. mkdir(dir, sftp);
  141. sftp.cd(dir);
  142. sftp.put(srcFile, fileName);
  143. }
  144. /**
  145. * 上传文件-sftp协议.
  146. * @param srcFile 源文件路径,/xxx/xxx.zip 或 x:/xxx/xxx.zip;
  147. * @param sftp sftp连接
  148. * @throws Exception 异常
  149. */
  150. public static void uploadFile(final String srcFile, final ChannelSftp sftp) throws Exception {
  151. try {
  152. File file = new File(srcFile);
  153. if (file.exists()) {
  154. List<String> list = formatPath(srcFile);
  155. uploadFile(srcFile, list.get(0), list.get(1), sftp);
  156. }
  157. } catch (Exception e) {
  158. exit(sftp);
  159. throw e;
  160. }
  161. }
  162. /**
  163. * 根据路径创建文件夹.
  164. * @param dir 路径 必须是 /xxx/xxx/xxx/ 不能就单独一个/
  165. * @param sftp sftp连接
  166. * @throws Exception 异常
  167. */
  168. public static boolean mkdir(final String dir, final ChannelSftp sftp) throws Exception {
  169. try {
  170. if (StringUtils.isBlank(dir))
  171. return false;
  172. String md = dir.replaceAll("\\\\", "/");
  173. if (md.indexOf("/") != 0 || md.length() == 1)
  174. return false;
  175. return mkdirs(md, sftp);
  176. } catch (Exception e) {
  177. exit(sftp);
  178. throw e;
  179. }
  180. }
  181. /**
  182. * 递归创建文件夹.
  183. * @param dir 路径
  184. * @param sftp sftp连接
  185. * @return 是否创建成功
  186. * @throws SftpException 异常
  187. */
  188. private static boolean mkdirs(final String dir, final ChannelSftp sftp) throws SftpException {
  189. String dirs = dir.substring(1, dir.length() - 1);
  190. String[] dirArr = dirs.split("/");
  191. String base = "";
  192. for (String d : dirArr) {
  193. base += "/" + d;
  194. if (dirExist(base + "/", sftp)) {
  195. continue;
  196. } else {
  197. sftp.mkdir(base + "/");
  198. }
  199. }
  200. return true;
  201. }
  202. /**
  203. * 判断文件夹是否存在.
  204. * @param dir 文件夹路径, /xxx/xxx/
  205. * @param sftp sftp协议
  206. * @return 是否存在
  207. */
  208. public static boolean dirExist(final String dir, final ChannelSftp sftp) {
  209. try {
  210. Vector<?> vector = sftp.ls(dir);
  211. if (null == vector)
  212. return false;
  213. else
  214. return true;
  215. } catch (SftpException e) {
  216. return false;
  217. }
  218. }
  219. /**
  220. * 格式化路径.
  221. * @param srcPath 原路径. /xxx/xxx/xxx.yyy 或 X:/xxx/xxx/xxx.yy
  222. * @return list, 第一个是路径(/xxx/xxx/),第二个是文件名(xxx.yy)
  223. */
  224. public static List<String> formatPath(final String srcPath) {
  225. List<String> list = new ArrayList<String>(2);
  226. String dir = "";
  227. String fileName = "";
  228. String repSrc = srcPath.replaceAll("\\\\", "/");
  229. int firstP = repSrc.indexOf("/");
  230. int lastP = repSrc.lastIndexOf("/");
  231. fileName = repSrc.substring(lastP + 1);
  232. dir = repSrc.substring(firstP, lastP);
  233. dir = PRE_FIX + (dir.length() == 1 ? dir : (dir + "/"));
  234. list.add(dir);
  235. list.add(fileName);
  236. return list;
  237. }
  238. /**
  239. * 关闭协议-sftp协议.
  240. * @param sftp sftp连接
  241. */
  242. public static void exit(final ChannelSftp sftp) {
  243. sftp.exit();
  244. }
  245. public static void main(String[] args) throws Exception {
  246. ChannelSftp sftp = getSftpConnect("192.168.0.35", 22, "root", "root");
  247. String pathString = "C:\\test\\aaa\\Foxmail7.zip";
  248. File file = new File(pathString);
  249. System.out.println("上传文件开始...");
  250. uploadFile(pathString, sftp);
  251. System.out.println("上传成功,开始删除本地文件...");
  252. file.delete();
  253. System.out.println("删除完成,开始校验本地文件...");
  254. if (!file.exists()) {
  255. System.out.println("文件不存在,开始从远程服务器获取...");
  256. download(pathString, pathString, sftp);
  257. System.out.println("下载完成");
  258. } else {
  259. System.out.println("在本地找到文件");
  260. }
  261. exit(sftp);
  262. System.exit(0);
  263. }
  264. }

v0.2-新增sftp连接池

由于创建sftp连接的花销比较大,因此考虑相同主机的连接存放在连接池中,下次获取sftp连接的时候直接去连接池获取
以下代码替换v0.1版的getSftpConnect()方法,并加上成员变量即可
[java] view plaincopy
  1. /**
  2. * sftp连接池.
  3. */
  4. private static final Map<String, Channel> SFTP_CHANNEL_POOL = new HashMap<String, Channel>();
  5. /**
  6. * 获取sftp协议连接.
  7. * @param host 主机名
  8. * @param port 端口
  9. * @param username 用户名
  10. * @param password 密码
  11. * @return 连接对象
  12. * @throws JSchException 异常
  13. */
  14. public static ChannelSftp getSftpConnect(final String host, final int port, final String username,
  15. final String password) throws JSchException {
  16. Session sshSession = null;
  17. Channel channel = null;
  18. ChannelSftp sftp = null;
  19. String key = host + "," + port + "," + username + "," + password;
  20. if (null == SFTP_CHANNEL_POOL.get(key)) {
  21. JSch jsch = new JSch();
  22. jsch.getSession(username, host, port);
  23. sshSession = jsch.getSession(username, host, port);
  24. sshSession.setPassword(password);
  25. Properties sshConfig = new Properties();
  26. sshConfig.put("StrictHostKeyChecking", "no");
  27. sshSession.setConfig(sshConfig);
  28. sshSession.connect();
  29. channel = sshSession.openChannel("sftp");
  30. channel.connect();
  31. SFTP_CHANNEL_POOL.put(key, channel);
  32. } else {
  33. channel = SFTP_CHANNEL_POOL.get(key);
  34. sshSession = channel.getSession();
  35. if (!sshSession.isConnected())
  36. sshSession.connect();
  37. if (!channel.isConnected())
  38. channel.connect();
  39. }
  40. sftp = (ChannelSftp) channel;
  41. return sftp;
  42. }

v0.3-修改了一些bug,新增递归删除文件夹功能

[java] view plaincopy
  1. package com.noryar.filesystem.utils;
  2. import java.io.ByteArrayOutputStream;
  3. import java.io.File;
  4. import java.io.FileOutputStream;
  5. import java.util.ArrayList;
  6. import java.util.HashMap;
  7. import java.util.List;
  8. import java.util.Map;
  9. import java.util.Properties;
  10. import java.util.Vector;
  11. import org.apache.commons.lang.StringUtils;
  12. import com.jcraft.jsch.Channel;
  13. import com.jcraft.jsch.ChannelSftp;
  14. import com.jcraft.jsch.ChannelSftp.LsEntry;
  15. import com.jcraft.jsch.JSch;
  16. import com.jcraft.jsch.JSchException;
  17. import com.jcraft.jsch.Session;
  18. import com.jcraft.jsch.SftpException;
  19. /**
  20. * 文件工具类.<br>
  21. * 1.所有的文件路径必须以'/'开头和结尾,否则路径最后一部分会被当做是文件名<br>
  22. * 2.方法出现异常的时候,会关闭sftp连接(但是不会关闭session和channel),异常会抛出
  23. * @author Leon Lee
  24. */
  25. public class SftpUtil {
  26. /**
  27. * 文件路径前缀. /ddit-remote
  28. */
  29. private static final String PRE_FIX = "/test-noryar";
  30. /**
  31. * sftp连接池.
  32. */
  33. private static final Map<String, Channel> SFTP_CHANNEL_POOL = new HashMap<String, Channel>();
  34. /**
  35. * 获取sftp协议连接.
  36. * @param host 主机名
  37. * @param port 端口
  38. * @param username 用户名
  39. * @param password 密码
  40. * @return 连接对象
  41. * @throws JSchException 异常
  42. */
  43. public static ChannelSftp getSftpConnect(final String host, final int port, final String username,
  44. final String password) throws JSchException {
  45. Session sshSession = null;
  46. Channel channel = null;
  47. ChannelSftp sftp = null;
  48. String key = host + "," + port + "," + username + "," + password;
  49. if (null == SFTP_CHANNEL_POOL.get(key)) {
  50. JSch jsch = new JSch();
  51. jsch.getSession(username, host, port);
  52. sshSession = jsch.getSession(username, host, port);
  53. sshSession.setPassword(password);
  54. Properties sshConfig = new Properties();
  55. sshConfig.put("StrictHostKeyChecking", "no");
  56. sshSession.setConfig(sshConfig);
  57. sshSession.connect();
  58. channel = sshSession.openChannel("sftp");
  59. channel.connect();
  60. SFTP_CHANNEL_POOL.put(key, channel);
  61. } else {
  62. channel = SFTP_CHANNEL_POOL.get(key);
  63. sshSession = channel.getSession();
  64. if (!sshSession.isConnected())
  65. sshSession.connect();
  66. if (!channel.isConnected())
  67. channel.connect();
  68. }
  69. sftp = (ChannelSftp) channel;
  70. return sftp;
  71. }
  72. /**
  73. * 下载文件-sftp协议.
  74. * @param downloadFile 下载的文件
  75. * @param saveFile 存在本地的路径
  76. * @param sftp sftp连接
  77. * @return 文件
  78. * @throws Exception 异常
  79. */
  80. public static File download(final String downloadFile, final String saveFile, final ChannelSftp sftp)
  81. throws Exception {
  82. FileOutputStream os = null;
  83. File file = new File(saveFile);
  84. try {
  85. if (!file.exists()) {
  86. File parentFile = file.getParentFile();
  87. if (!parentFile.exists()) {
  88. parentFile.mkdirs();
  89. }
  90. file.createNewFile();
  91. }
  92. os = new FileOutputStream(file);
  93. List<String> list = formatPath(downloadFile);
  94. sftp.get(list.get(0) + list.get(1), os);
  95. } catch (Exception e) {
  96. exit(sftp);
  97. e.getMessage();
  98. throw e;
  99. } finally {
  100. os.close();
  101. }
  102. return file;
  103. }
  104. /**
  105. * 下载文件-sftp协议.
  106. * @param downloadFile 下载的文件
  107. * @param saveFile 存在本地的路径
  108. * @param sftp sftp连接
  109. * @return 文件 byte[]
  110. * @throws Exception 异常
  111. */
  112. public static byte[] downloadAsByte(final String downloadFile, final ChannelSftp sftp) throws Exception {
  113. ByteArrayOutputStream os = new ByteArrayOutputStream();
  114. try {
  115. List<String> list = formatPath(downloadFile);
  116. sftp.get(list.get(0) + list.get(1), os);
  117. } catch (Exception e) {
  118. exit(sftp);
  119. throw e;
  120. } finally {
  121. os.close();
  122. }
  123. return os.toByteArray();
  124. }
  125. /**
  126. * 删除文件-sftp协议.
  127. * @param pathString 要删除的文件
  128. * @param sftp sftp连接
  129. * @throws Exception 异常
  130. */
  131. public static void rmFile(final String pathString, final ChannelSftp sftp) throws Exception {
  132. try {
  133. List<String> list = formatPath(pathString);
  134. sftp.rm(list.get(0) + list.get(1));
  135. } catch (Exception e) {
  136. exit(sftp);
  137. throw e;
  138. }
  139. }
  140. /**
  141. * 删除文件夹-sftp协议.如果文件夹有内容,则会抛出异常.
  142. * @param pathString 文件夹路径
  143. * @param sftp sftp连接
  144. * @param resursion 递归删除
  145. * @throws Exception 异常
  146. */
  147. public static void rmDir(final String pathString, final ChannelSftp sftp, final boolean recursion) throws Exception {
  148. try {
  149. String fp = formatPath(pathString).get(0);
  150. if (recursion)
  151. exeRmRec(fp, sftp);
  152. else
  153. sftp.rmdir(fp);
  154. } catch (Exception e) {
  155. exit(sftp);
  156. throw e;
  157. }
  158. }
  159. /**
  160. * 递归删除执行.
  161. * @param pathString 文件路径
  162. * @param sftp sftp连接
  163. * @throws SftpException
  164. */
  165. private static void exeRmRec(final String pathString, final ChannelSftp sftp) throws SftpException {
  166. @SuppressWarnings("unchecked")
  167. Vector<LsEntry> vector = sftp.ls(pathString);
  168. if (vector.size() == 1) { // 文件,直接删除
  169. sftp.rm(pathString);
  170. } else if (vector.size() == 2) { // 空文件夹,直接删除
  171. sftp.rmdir(pathString);
  172. } else {
  173. String fileName = "";
  174. // 删除文件夹下所有文件
  175. for (LsEntry en : vector) {
  176. fileName = en.getFilename();
  177. if (".".equals(fileName) || "..".equals(fileName)) {
  178. continue;
  179. } else {
  180. exeRmRec(pathString + "/" + fileName, sftp);
  181. }
  182. }
  183. // 删除文件夹
  184. sftp.rmdir(pathString);
  185. }
  186. }
  187. /**
  188. * 上传文件-sftp协议.
  189. * @param srcFile 源文件
  190. * @param dir 保存路径
  191. * @param fileName 保存文件名
  192. * @param sftp sftp连接
  193. * @throws Exception 异常
  194. */
  195. private static void uploadFile(final String srcFile, final String dir, final String fileName, final ChannelSftp sftp)
  196. throws Exception {
  197. mkdir(dir, sftp);
  198. sftp.cd(dir);
  199. sftp.put(srcFile, fileName);
  200. }
  201. /**
  202. * 上传文件-sftp协议.
  203. * @param srcFile 源文件路径,/xxx/xx.yy 或 x:/xxx/xxx.yy
  204. * @param sftp sftp连接
  205. * @return 上传成功与否
  206. * @throws Exception 异常
  207. */
  208. public static boolean uploadFile(final String srcFile, final ChannelSftp sftp) throws Exception {
  209. try {
  210. File file = new File(srcFile);
  211. if (file.exists()) {
  212. List<String> list = formatPath(srcFile);
  213. uploadFile(srcFile, list.get(0), list.get(1), sftp);
  214. return true;
  215. }
  216. return false;
  217. } catch (Exception e) {
  218. exit(sftp);
  219. throw e;
  220. }
  221. }
  222. /**
  223. * 根据路径创建文件夹.
  224. * @param dir 路径 必须是 /xxx/xxx/ 不能就单独一个/
  225. * @param sftp sftp连接
  226. * @throws Exception 异常
  227. */
  228. public static boolean mkdir(final String dir, final ChannelSftp sftp) throws Exception {
  229. try {
  230. if (StringUtils.isBlank(dir))
  231. return false;
  232. String md = dir.replaceAll("\\\\", "/");
  233. if (md.indexOf("/") != 0 || md.length() == 1)
  234. return false;
  235. return mkdirs(md, sftp);
  236. } catch (Exception e) {
  237. exit(sftp);
  238. throw e;
  239. }
  240. }
  241. /**
  242. * 递归创建文件夹.
  243. * @param dir 路径
  244. * @param sftp sftp连接
  245. * @return 是否创建成功
  246. * @throws SftpException 异常
  247. */
  248. private static boolean mkdirs(final String dir, final ChannelSftp sftp) throws SftpException {
  249. String dirs = dir.substring(1, dir.length() - 1);
  250. String[] dirArr = dirs.split("/");
  251. String base = "";
  252. for (String d : dirArr) {
  253. base += "/" + d;
  254. if (dirExist(base + "/", sftp)) {
  255. continue;
  256. } else {
  257. sftp.mkdir(base + "/");
  258. }
  259. }
  260. return true;
  261. }
  262. /**
  263. * 判断文件夹是否存在.
  264. * @param dir 文件夹路径, /xxx/xxx/
  265. * @param sftp sftp协议
  266. * @return 是否存在
  267. */
  268. private static boolean dirExist(final String dir, final ChannelSftp sftp) {
  269. try {
  270. Vector<?> vector = sftp.ls(dir);
  271. if (null == vector)
  272. return false;
  273. else
  274. return true;
  275. } catch (SftpException e) {
  276. return false;
  277. }
  278. }
  279. /**
  280. * 格式化路径.
  281. * @param srcPath 原路径. /xxx/xxx/xxx.yyy 或 X:/xxx/xxx/xxx.yy
  282. * @return list, 第一个是路径(/xxx/xxx/),第二个是文件名(xxx.yy)
  283. */
  284. public static List<String> formatPath(final String srcPath) {
  285. List<String> list = new ArrayList<String>(2);
  286. String repSrc = srcPath.replaceAll("\\\\", "/");
  287. int firstP = repSrc.indexOf("/");
  288. int lastP = repSrc.lastIndexOf("/");
  289. String fileName = lastP + 1 == repSrc.length() ? "" : repSrc.substring(lastP + 1);
  290. String dir = firstP == -1 ? "" : repSrc.substring(firstP, lastP);
  291. dir = PRE_FIX + (dir.length() == 1 ? dir : (dir + "/"));
  292. list.add(dir);
  293. list.add(fileName);
  294. return list;
  295. }
  296. /**
  297. * 关闭协议-sftp协议.
  298. * @param sftp sftp连接
  299. */
  300. public static void exit(final ChannelSftp sftp) {
  301. sftp.exit();
  302. }
  303. public static void main(String[] args) throws Exception {
  304. ChannelSftp sftp = getSftpConnect("192.168.0.35", 22, "root", "root");
  305. // String pathString = "C:\\test\\ccc\\Foxmail7.zip";
  306. // File file = new File(pathString);
  307. // System.out.println("上传文件开始...");
  308. // uploadFile(pathString, sftp);
  309. // System.out.println("上传成功,开始删除本地文件...");
  310. // file.delete();
  311. // System.out.println("删除完成,开始校验本地文件...");
  312. // if (!file.exists()) {
  313. // System.out.println("文件不存在,开始从远程服务器获取...");
  314. // download(pathString, pathString, sftp);
  315. // System.out.println("下载完成");
  316. // } else {
  317. // System.out.println("在本地找到文件");
  318. // }
  319. rmDir("", sftp, true);
  320. exit(sftp);
  321. System.exit(0);
  322. }
  323. }

v0.31

修正连接关闭,将关闭的方法改成私有,不允许使用者自行关闭(否则会导致连接池获取错误)
优化删除文件及文件夹,先判断文件或文件夹是否存在,然后再删除
[java] view plaincopy
  1. package com.noryar.filesystem.utils;
  2. import java.io.ByteArrayOutputStream;
  3. import java.io.File;
  4. import java.io.FileOutputStream;
  5. import java.util.ArrayList;
  6. import java.util.HashMap;
  7. import java.util.List;
  8. import java.util.Map;
  9. import java.util.Properties;
  10. import java.util.Vector;
  11. import org.apache.commons.lang.StringUtils;
  12. import com.jcraft.jsch.Channel;
  13. import com.jcraft.jsch.ChannelSftp;
  14. import com.jcraft.jsch.ChannelSftp.LsEntry;
  15. import com.jcraft.jsch.JSch;
  16. import com.jcraft.jsch.JSchException;
  17. import com.jcraft.jsch.Session;
  18. import com.jcraft.jsch.SftpException;
  19. /**
  20. * 文件工具类.<br>
  21. * 1.所有的文件路径必须以'/'开头和结尾,否则路径最后一部分会被当做是文件名<br>
  22. * 2. @since version-0.3 方法出现异常的时候,<del>会关闭sftp连接(但是不会关闭session和channel)</del>(del @ version 0.31),异常会抛出<br>
  23. * @author Leon Lee
  24. */
  25. public class SftpUtil {
  26. /**
  27. * 文件路径前缀. /ddit-remote
  28. */
  29. private static final String PRE_FIX = "/test-noryar";
  30. /**
  31. * sftp连接池.
  32. */
  33. private static final Map<String, Channel> SFTP_CHANNEL_POOL = new HashMap<String, Channel>();
  34. /**
  35. * 获取sftp协议连接.
  36. * @param host 主机名
  37. * @param port 端口
  38. * @param username 用户名
  39. * @param password 密码
  40. * @return 连接对象
  41. * @throws JSchException 异常
  42. */
  43. public static ChannelSftp getSftpConnect(final String host, final int port, final String username,
  44. final String password) throws JSchException {
  45. Session sshSession = null;
  46. Channel channel = null;
  47. ChannelSftp sftp = null;
  48. String key = host + "," + port + "," + username + "," + password;
  49. if (null == SFTP_CHANNEL_POOL.get(key)) {
  50. JSch jsch = new JSch();
  51. jsch.getSession(username, host, port);
  52. sshSession = jsch.getSession(username, host, port);
  53. sshSession.setPassword(password);
  54. Properties sshConfig = new Properties();
  55. sshConfig.put("StrictHostKeyChecking", "no");
  56. sshSession.setConfig(sshConfig);
  57. sshSession.connect();
  58. channel = sshSession.openChannel("sftp");
  59. channel.connect();
  60. SFTP_CHANNEL_POOL.put(key, channel);
  61. } else {
  62. channel = SFTP_CHANNEL_POOL.get(key);
  63. sshSession = channel.getSession();
  64. if (!sshSession.isConnected())
  65. sshSession.connect();
  66. if (!channel.isConnected())
  67. channel.connect();
  68. }
  69. sftp = (ChannelSftp) channel;
  70. return sftp;
  71. }
  72. /**
  73. * 下载文件-sftp协议.
  74. * @param downloadFile 下载的文件
  75. * @param saveFile 存在本地的路径
  76. * @param sftp sftp连接
  77. * @return 文件
  78. * @throws Exception 异常
  79. */
  80. public static File download(final String downloadFile, final String saveFile, final ChannelSftp sftp)
  81. throws Exception {
  82. FileOutputStream os = null;
  83. File file = new File(saveFile);
  84. try {
  85. if (!file.exists()) {
  86. File parentFile = file.getParentFile();
  87. if (!parentFile.exists()) {
  88. parentFile.mkdirs();
  89. }
  90. file.createNewFile();
  91. }
  92. os = new FileOutputStream(file);
  93. List<String> list = formatPath(downloadFile);
  94. sftp.get(list.get(0) + list.get(1), os);
  95. } catch (Exception e) {
  96. throw e;
  97. } finally {
  98. os.close();
  99. }
  100. return file;
  101. }
  102. /**
  103. * 下载文件-sftp协议.
  104. * @param downloadFile 下载的文件
  105. * @param saveFile 存在本地的路径
  106. * @param sftp sftp连接
  107. * @return 文件 byte[]
  108. * @throws Exception 异常
  109. */
  110. public static byte[] downloadAsByte(final String downloadFile, final ChannelSftp sftp) throws Exception {
  111. ByteArrayOutputStream os = new ByteArrayOutputStream();
  112. try {
  113. List<String> list = formatPath(downloadFile);
  114. sftp.get(list.get(0) + list.get(1), os);
  115. } catch (Exception e) {
  116. throw e;
  117. } finally {
  118. os.close();
  119. }
  120. return os.toByteArray();
  121. }
  122. /**
  123. * 删除文件-sftp协议.
  124. * @param pathString 要删除的文件
  125. * @param sftp sftp连接
  126. * @throws SftpException 异常
  127. */
  128. public static void rmFile(final String pathString, final ChannelSftp sftp) throws SftpException {
  129. List<String> list = formatPath(pathString);
  130. String dir = list.get(0);
  131. String file = list.get(1);
  132. if (dirExist(dir + file, sftp)) {
  133. sftp.rm(list.get(0) + list.get(1));
  134. }
  135. }
  136. /**
  137. * 删除文件夹-sftp协议.如果文件夹有内容,则会抛出异常.
  138. * @param pathString 文件夹路径
  139. * @param sftp sftp连接
  140. * @param resursion 递归删除
  141. * @throws SftpException 异常
  142. */
  143. public static void rmDir(final String pathString, final ChannelSftp sftp, final boolean recursion)
  144. throws SftpException {
  145. String fp = formatPath(pathString).get(0);
  146. if (dirExist(fp, sftp)) {
  147. if (recursion)
  148. exeRmRec(fp, sftp);
  149. else
  150. sftp.rmdir(fp);
  151. }
  152. }
  153. /**
  154. * 递归删除执行.
  155. * @param pathString 文件路径
  156. * @param sftp sftp连接
  157. * @throws SftpException
  158. */
  159. private static void exeRmRec(final String pathString, final ChannelSftp sftp) throws SftpException {
  160. @SuppressWarnings("unchecked")
  161. Vector<LsEntry> vector = sftp.ls(pathString);
  162. if (vector.size() == 1) { // 文件,直接删除
  163. sftp.rm(pathString);
  164. } else if (vector.size() == 2) { // 空文件夹,直接删除
  165. sftp.rmdir(pathString);
  166. } else {
  167. String fileName = "";
  168. // 删除文件夹下所有文件
  169. for (LsEntry en : vector) {
  170. fileName = en.getFilename();
  171. if (".".equals(fileName) || "..".equals(fileName)) {
  172. continue;
  173. } else {
  174. exeRmRec(pathString + "/" + fileName, sftp);
  175. }
  176. }
  177. // 删除文件夹
  178. sftp.rmdir(pathString);
  179. }
  180. }
  181. /**
  182. * 上传文件-sftp协议.
  183. * @param srcFile 源文件
  184. * @param dir 保存路径
  185. * @param fileName 保存文件名
  186. * @param sftp sftp连接
  187. * @throws Exception 异常
  188. */
  189. private static void uploadFile(final String srcFile, final String dir, final String fileName, final ChannelSftp sftp)
  190. throws SftpException {
  191. mkdir(dir, sftp);
  192. sftp.cd(dir);
  193. sftp.put(srcFile, fileName);
  194. }
  195. /**
  196. * 上传文件-sftp协议.
  197. * @param srcFile 源文件路径,/xxx/xx.yy 或 x:/xxx/xxx.yy
  198. * @param sftp sftp连接
  199. * @return 上传成功与否
  200. * @throws SftpException 异常
  201. */
  202. public static boolean uploadFile(final String srcFile, final ChannelSftp sftp) throws SftpException {
  203. File file = new File(srcFile);
  204. if (file.exists()) {
  205. List<String> list = formatPath(srcFile);
  206. uploadFile(srcFile, list.get(0), list.get(1), sftp);
  207. return true;
  208. }
  209. return false;
  210. }
  211. /**
  212. * 根据路径创建文件夹.
  213. * @param dir 路径 必须是 /xxx/xxx/ 不能就单独一个/
  214. * @param sftp sftp连接
  215. * @throws SftpException 异常
  216. */
  217. public static boolean mkdir(final String dir, final ChannelSftp sftp) throws SftpException {
  218. if (StringUtils.isBlank(dir))
  219. return false;
  220. String md = dir.replaceAll("\\\\", "/");
  221. if (md.indexOf("/") != 0 || md.length() == 1)
  222. return false;
  223. return mkdirs(md, sftp);
  224. }
  225. /**
  226. * 递归创建文件夹.
  227. * @param dir 路径
  228. * @param sftp sftp连接
  229. * @return 是否创建成功
  230. * @throws SftpException 异常
  231. */
  232. private static boolean mkdirs(final String dir, final ChannelSftp sftp) throws SftpException {
  233. String dirs = dir.substring(1, dir.length() - 1);
  234. String[] dirArr = dirs.split("/");
  235. String base = "";
  236. for (String d : dirArr) {
  237. base += "/" + d;
  238. if (dirExist(base + "/", sftp)) {
  239. continue;
  240. } else {
  241. sftp.mkdir(base + "/");
  242. }
  243. }
  244. return true;
  245. }
  246. /**
  247. * 判断文件夹是否存在.
  248. * @param dir 文件夹路径, /xxx/xxx/
  249. * @param sftp sftp协议
  250. * @return 是否存在
  251. */
  252. private static boolean dirExist(final String dir, final ChannelSftp sftp) {
  253. try {
  254. Vector<?> vector = sftp.ls(dir);
  255. if (null == vector)
  256. return false;
  257. else
  258. return true;
  259. } catch (SftpException e) {
  260. return false;
  261. }
  262. }
  263. /**
  264. * 格式化路径.
  265. * @param srcPath 原路径. /xxx/xxx/xxx.yyy 或 X:/xxx/xxx/xxx.yy
  266. * @return list, 第一个是路径(/xxx/xxx/),第二个是文件名(xxx.yy)
  267. */
  268. public static List<String> formatPath(final String srcPath) {
  269. List<String> list = new ArrayList<String>(2);
  270. String repSrc = srcPath.replaceAll("\\\\", "/");
  271. int firstP = repSrc.indexOf("/");
  272. int lastP = repSrc.lastIndexOf("/");
  273. String fileName = lastP + 1 == repSrc.length() ? "" : repSrc.substring(lastP + 1);
  274. String dir = firstP == -1 ? "" : repSrc.substring(firstP, lastP);
  275. dir = PRE_FIX + (dir.length() == 1 ? dir : (dir + "/"));
  276. list.add(dir);
  277. list.add(fileName);
  278. return list;
  279. }
  280. /**
  281. * 关闭协议-sftp协议.(关闭会导致连接池异常,因此不建议用户自定义关闭)
  282. * @param sftp sftp连接
  283. */
  284. private static void exit(final ChannelSftp sftp) {
  285. sftp.exit();
  286. }
  287. public static void main(String[] args) throws Exception {
  288. ChannelSftp sftp = getSftpConnect("192.168.0.35", 22, "root", "root");
  289. // String pathString = "C:\\test\\ccc\\Foxmail7.zip";
  290. // File file = new File(pathString);
  291. // System.out.println("上传文件开始...");
  292. // uploadFile(pathString, sftp);
  293. // System.out.println("上传成功,开始删除本地文件...");
  294. // file.delete();
  295. // System.out.println("删除完成,开始校验本地文件...");
  296. // if (!file.exists()) {
  297. // System.out.println("文件不存在,开始从远程服务器获取...");
  298. // download(pathString, pathString, sftp);
  299. // System.out.println("下载完成");
  300. // } else {
  301. // System.out.println("在本地找到文件");
  302. // }
  303. // rmDir("", sftp, true);
  304. String path = "E:\\aaa.zip";
  305. File file = SftpUtil.download(path, path, sftp);
  306. // SftpUtil.exit(sftp);
  307. exit(sftp);
  308. System.exit(0);
  309. }
  310. }

转载于:https://www.cnblogs.com/ceshi2016/p/7519788.html

文件系统之-JAVA Sftp远程操作:相关推荐

  1. 在Eclipse中运行JAVA代码远程操作HBase的示例

    2019独角兽企业重金招聘Python工程师标准>>> 下面是一个在Windows的Eclipse中通过JAVA操作一个Linux上运行的hbase的示例. Hbase的配置需要注意 ...

  2. java使用Jsch实现远程操作linux服务器进行文件上传、下载,删除和显示目录信息...

    1.java使用Jsch实现远程操作linux服务器进行文件上传.下载,删除和显示目录信息. 参考链接:https://www.cnblogs.com/longyg/archive/2012/06/2 ...

  3. Java网页数据采集器[续篇-远程操作]

    本期概述 上期我们学习了html页面采集后的数据查询, 但这仅仅是在本地查询数据库,如果我们想通过远程操作来进行数据的采集,存储和查询,那又该怎么做呢? 今天我们一起来学习下:如何通过本地客户端远程访 ...

  4. JSch:Java Secure Channel -- java 代码实现 ssh 远程操作

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. JSch 是SSH2的一个纯Java实现. 它允许你连接到一个 sshd 服务器,使用端口转发,X1 ...

  5. java读取文件服务器文件,java读取远程服务器文件

    java读取远程服务器文件 内容精选 换一换 已成功登录Java性能分析.待安装Guardian的服务器已开启sshd.待安装Guardian的服务器已安装JRE,JRE版本要求为Huawei JDK ...

  6. 5.WEB及远程操作

    WEB及远程操作 1.Spring MVC总结 1.1 Spring MVC 框架请求处理流程 1.2 Spring MVC框架包含内容 1.3 Spring MVC 核心 1.3.1 Dispatc ...

  7. java 跨服务器 文件拷贝,java拷贝远程服务器上文件

    java拷贝远程服务器上文件 内容精选 换一换 已成功登录Java性能分析.待安装Guardian的服务器已开启sshd.待安装Guardian的服务器已安装JRE,JRE版本要求为Huawei JD ...

  8. java读远程服务器文件,java 读取远程服务器文件

    java 读取远程服务器文件 [2021-01-31 12:09:45]  简介: php去除nbsp的方法:首先创建一个PHP代码示例文件:然后通过"preg_replace(" ...

  9. 关于Hadoop多用户管理支持客户端远程操作的理论总结

    1.问题 Hadoop客户端如何配置可远程操作Hadoop:Hadoop多用户情况下,是如何管理权限并分配存储空间和计算能力,保证集群的稳定. 2.Hadoop平台 要理解客户端如何通过指定用户远程操 ...

最新文章

  1. 混合mixin函数_Less 混合
  2. 真香!一行Python代码,帮你制作小姐姐的表情包,靠谱吗?
  3. SAP Webclient UI和Fiori UI的混搭
  4. Android之提示android.content.res.Resources$NotFoundException: Resource ID #0x7f08010a
  5. c#中textbox属性_C#.Net中的TextBox.MaxLength属性与示例
  6. cemtos7上mysql8两个实例_centos7上配置mysql8的双主互写
  7. java实验检查危险品代码_2019JAVA第六次实验报告
  8. Activity生命周期(二)
  9. python excel 提取特定行_Python之从Excel一列内提取数字
  10. 尚硅谷python全套-尚硅谷Java视频教程,粉丝无数,人手一套尚硅谷教程
  11. python装饰器两层和三层_2020 python学习第十六天————三层装饰器与迭代器
  12. 转载 《TypeScript 类型定义 DefinitelyTyped》
  13. python选择时间窗口_对pandas中时间窗函数rolling的使用详解
  14. 教你如何轻松玩转自媒体淘客,赚大钱!
  15. 机器学习方法的基本分类
  16. struct字节计算
  17. leetcode46题 php实现,Leetcode PHP题解--D46 893. Groups of Special-Equivalent Strings
  18. 《深入理解Java虚拟机》内存管理机制 部分 读书笔记
  19. 数学建模学习1.22——多元回归分析
  20. [Unity Mirror] Network Discovery

热门文章

  1. Linux CentOS 修改服务器主机名hostname
  2. java web轻量级开发面试教程内容精粹:哪些简历得不到面试机会
  3. Android Wear 唤醒热词会比“你好,安卓”好吗?
  4. Center os vi
  5. 黄聪: Bootstrap之Form表单验证神器: BootstrapValidator(转)
  6. centos关机与重启命令详解
  7. 主成分分析(PCA)算法,K-L变换 角度
  8. Oracle 查看 对象 持有锁的情况
  9. android Drawable.mutate()的使用
  10. github 分支管理