Java 通过FTP与SFTP 方式, 实现 文件的上传下载 删除操作

1. FTP

FTP通讯协议采用客户机 / 服务器(Client / Server )架构。用户可以通过各种不同的FTP客户端程序,借助FTP协议,来连接FTP服务器,以上传或者下载文件。

默认端口: 21

  • 在此协议中SSH2服务器起了一个桥梁作用,把数据在客户端和ftp之间转发。ftp协议本身包括两个通道,一个是控制通道,另一个是数据通道。

Java 通过FTP与SFTP 方式, 实现 文件的上传下载 删除操作_第1张图片

2. SFTP

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

  • sftp是ssh内含的协议,只要sshd服务器启动了,它就可用,它本身不需要ftp服务器启动
  • 它是作为SSH2的一个子服务工作的

Java 通过FTP与SFTP 方式, 实现 文件的上传下载 删除操作_第2张图片

3. SFTP 和FTPS的区别

1、安全通道

FTP 不提供任何安全通道来在主机之间传输文件;而SFTP协议提供了一个安全通道,用于在网络上的主机之间传输文件。

2、使用的协议

FTP使用TCP / IP协议。而,SFTP是SSH协议的一部分,它是一种远程登录信息。

3、链接方式

FTP使用TCP端口21上的控制连接建立连接。而,SFTP是在客户端和服务器之间通过SSH协议(TCP端口22)建立的安全连接来传输文件。

4、安全性

FTP密码和数据以纯文本格式发送,大多数情况下是不加密的,安全性不高。而,SFTP会在发送之前加密数据,二进制的形式传递,是无法“按原样”阅读的,安全性较高。

4. JAVA下针对于FTP实现上传下载工具类

import java.io.*;

import org.apache.commons.io.IOUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

/**
 * @Author: xiezb
 * @Date: 2019/9/23 10:14
 * @Description: ftp上传下载工具类
 */
@SuppressWarnings("ALL")
public class FtpUtil {
    /**文件编码*/
    private static String CODE = "UTF-8";
    /** ftp服务编码*/
    private static String SERVER_CODE = "ISO-8859-1";

    /**
     * 获取FTP连接 
* @param host FTP服务器hostname
* @param port FTP服务器端口
* @param username FTP登录账号
* @param password FTP登录密码
* @return FTPClient对象
*/
public static FTPClient getFTPConnect(String host, int port, String username, String password) { FTPClient ftp = new FTPClient(); try { int reply; //1.连接服务器 ftp.connect(host, port); //2.登录服务器 如果采用默认端口,可以使用ftp.connect(url)的方式直接连接FTP服务器 ftp.login(username, password); //3.判断登陆是否成功 reply = ftp.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftp.disconnect(); return null; } //ftp.setFileType(FTPClient.BINARY_FILE_TYPE);//@fix 设置二进制解决偶有图图片传输失真问题 return ftp; } catch (IOException e) { e.printStackTrace(); closeFTP(ftp); } return null; } /** * 关闭FTP连接,释放资源
* @param ftpClient 连接对象
*/
public static void closeFTP(FTPClient ftpClient) { if (!ObjectUtil.isEmptyObject(ftpClient) && ftpClient.isConnected()) { try { ftpClient.logout(); } catch (IOException e) { e.printStackTrace(); } finally { try { ftpClient.disconnect(); } catch (IOException e) { e.printStackTrace(); } } } } /** * Description: 向FTP服务器上传文件
* @param ftp 连接对象
* @param basePath FTP服务器基础目录
* @param filePath FTP服务器文件存放路径。文件的路径为basePath+filePath
* @param filename 上传到FTP服务器上的文件名
* @param input 输入流
* @return 成功返回true,否则返回false
*/
public static boolean uploadFile(FTPClient ftp, String basePath, String filePath, String filename, InputStream input) { try { if (ObjectUtil.isEmptyObject(ftp)) { return false; } if (!ObjectUtil.isEmptyObject(basePath)) { basePath = basePath.replace("\\", "/"); // 配置中可能配置的是windows的,换Linux "/" basePath = basePath.endsWith("/") ? basePath.substring(0, basePath.length() - 1) : basePath; } String tempPath = basePath; if (!ObjectUtil.isEmptyObject(filePath)) { filePath = filePath.replace("\\", "/"); // 配置中可能配置的是windows的,换Linux "/" if (filePath.startsWith("/")) { tempPath += filePath; } else { if (ObjectUtil.isEmptyObject(tempPath)) { tempPath = filePath; } else { tempPath = tempPath + "/" + filePath; } } } //切换到上传目录 if (!ftp.changeWorkingDirectory(tempPath)) { //如果目录不存在创建目录 String[] dirs = tempPath.split("/"); String path = ""; for (String dir : dirs) { if (ObjectUtil.isEmptyObject(dir)) continue; if (tempPath.startsWith("/")) { path += "/" + dir; } else { if (ObjectUtil.isEmptyObject(path)) { path += dir; } else { path += "/" + dir; } } if (!ftp.changeWorkingDirectory(path)) { //进不去目录,说明该目录不存在 if (!ftp.makeDirectory(path)) { //创建目录 //如果创建文件目录失败,则返回 System.out.println("创建文件目录"+path+"失败"); return false; } else { //目录存在,则直接进入该目录 ftp.changeWorkingDirectory(path); } } } } //设置上传文件的类型为二进制类型 ftp.setFileType(FTP.BINARY_FILE_TYPE); //上传文件 filename = new String(filename.getBytes(CODE), SERVER_CODE); if (!ftp.storeFile(filename, input)) { return false; } return true; } catch (IOException e) { e.printStackTrace(); } finally { closeFTP(ftp); } return false; } /** * Description: 从FTP服务器下载文件
* @param ftp 连接对象
* @param remotePath FTP服务器上的相对路径
* @param fileName 要下载的文件名
* @param localPath 下载后保存到本地的路径
* @return 结果:
* true: 成功; false: 失败
*/
public static boolean downloadFile(FTPClient ftp, String remotePath, String fileName, String localPath) { try { if (ObjectUtil.isEmptyObject(ftp)) { return false; } ftp.setControlEncoding(CODE); ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目录 FTPFile[] fs = ftp.listFiles(); for (FTPFile ff : fs) { if (ff.getName().equals(fileName)) { localPath = localPath.replace("\\", File.separator); localPath = localPath + (localPath.endsWith(File.separator) ? fileName : "/" + fileName); File file = file = new File(localPath); if (file.exists()) { file.delete(); } file.createNewFile(); file = new File(localPath); OutputStream is = new FileOutputStream(file); ftp.retrieveFile(ff.getName(), is); is.close(); } } return true; } catch (IOException e) { e.printStackTrace(); } finally { closeFTP(ftp); } return false; } /** * Description: 从FTP服务器下载文件
* @param ftp 连接对象
* @param remotePath FTP服务器上的相对路径
* @param fileName 要下载的文件名
* @return 结果: 文件的二进制数组
* */
public static byte[] downloadFile(FTPClient ftp, String remotePath, String fileName) { byte[] bytes = null; try { if (ObjectUtil.isEmptyObject(ftp)) { return null; } ftp.setControlEncoding(CODE); ftp.setFileType(ftp.BINARY_FILE_TYPE); ftp.setBufferSize(1024); ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目录 FTPFile[] fs = ftp.listFiles(); for (FTPFile ff : fs) { if (ff.getName().equals(fileName)) { String remoteAbsoluteFile = ff.getName(); remoteAbsoluteFile = new String(remoteAbsoluteFile.getBytes(CODE), SERVER_CODE); InputStream in = ftp.retrieveFileStream(remoteAbsoluteFile); bytes = IOUtils.toByteArray(in); System.out.println("下载成功!" + bytes.length); in.close(); } } } catch (IOException e) { e.printStackTrace(); } finally { closeFTP(ftp); } return bytes; } /** * 文件转成 byte[] * @param inStream * @return * @throws IOException */ public static byte[] input2byte(InputStream inStream) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(1024); byte[] b = new byte[1024]; int len = -1; while((len = inStream.read(b)) != -1) { bos.write(b, 0, len); } bos.flush(); byte[] in2b = bos.toByteArray(); bos.close(); return in2b; } /** * 删除文件-FTP方式
* * @param ftp FTPClient对象
* @param ftpPath FTP服务器上传地址
* @param ftpFileName FTP服务器上要删除的文件名
* @return */
public static void deleteFile(FTPClient ftp, String ftpPath, String ftpFileName) throws Exception{ try { ftp.changeWorkingDirectory(ftpPath);//转移到指定FTP服务器目录 ftpFileName = new String(ftpFileName.getBytes(CODE), SERVER_CODE); ftp.deleteFile(ftpFileName); } catch (Exception e){ e.printStackTrace(); throw e; } finally { closeFTP(ftp); } } //ftp上传文件测试main函数 public static void main(String[] args) { try { FileInputStream in=new FileInputStream(new File("F:\\abc\\201909\\哈哈.txt")); FTPClient ftp = getFTPConnect("ip",21,"用户名","密码"); // 上传 boolean flag = uploadFile(ftp, "","上传路径目录", "哈哈.txt", in); } catch (Exception e) { e.printStackTrace(); } } }

5. Java操作SFTP 工具类

import com.jcraft.jsch.*;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Properties;
import java.util.Vector;
/**
 * @Author: xiezb
 * @Date: 2019/9/23 13:13
 * @Description: 类说明 sftp工具类
 */
@SuppressWarnings("ALL")
public class SFTPUtil {
    private transient Logger log = LoggerFactory.getLogger(this.getClass());

    private ChannelSftp sftp;
    private Session session;
    /** SFTP 登录用户名*/
    private String username;
    /** SFTP 登录密码*/
    private String password;
    /** 私钥 */
    private String privateKey;
    /** SFTP 服务器地址IP地址*/
    private String host;
    /** SFTP 端口*/
    private int port;
    /**默认连接超时*/
    private static Integer timeOut = 20000;

    /**文件编码*/
    private static String FILE_CODE = "UTF-8";

    /**
     *  构造基于密码认证的sftp对象 
* @param host 主机
* @param port 端口号
* @param username 用户名
* @param password 密码
*/
public SFTPUtil(String host, int port, String username, String password) { this.username = username; this.password = password; this.host = host; this.port = port; } /** * 构造基于秘钥认证的sftp对象
* @param username 用户名
* @param host 主机
* @param port 端口
* @param privateKey 私钥
*/
public SFTPUtil(String username, String host, int port, String privateKey) { this.username = username; this.host = host; this.port = port; this.privateKey = privateKey; } public SFTPUtil(){} /** * 连接sftp服务器 */ public void login(){ try { JSch jsch = new JSch(); if (privateKey != null) { jsch.addIdentity(privateKey);// 设置私钥 } session = jsch.getSession(username, host, port); if (password != null) { session.setPassword(password); } Properties config = new Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); session.setTimeout(timeOut); session.connect(); Channel channel = session.openChannel("sftp"); channel.connect(); sftp = (ChannelSftp) channel; sftp.setFilenameEncoding(FILE_CODE); } catch (Exception e) { e.printStackTrace(); this.logout(); } } /** * 关闭连接 server */ public void logout(){ if (!ObjectUtil.isEmptyObject(sftp)) { if (sftp.isConnected()) { sftp.disconnect(); } } if (!ObjectUtil.isEmptyObject(session)) { if (session.isConnected()) { session.disconnect(); } } } /** * 将输入流的数据上传到sftp作为文件。文件完整路径=basePath+directory
* @param basePath 服务器的基础路径
* @param directory 上传到该目录
* @param sftpFileName sftp端文件名
* @param input 输入流
*/
public boolean uploadFile(String basePath,String directory, String sftpFileName, InputStream input) throws SftpException{ String tempPath = ""; try { if (!ObjectUtil.isEmptyObject(basePath)) { basePath = basePath.replace("\\", "/"); // 配置中可能配置的是windows的,换Linux "/" basePath = basePath.endsWith("/") ? basePath.substring(0, basePath.length() - 1) : basePath; } tempPath = basePath; if (!ObjectUtil.isEmptyObject(directory)) { directory = directory.replace("\\", "/"); // 配置中可能配置的是windows的,换Linux "/" if (directory.startsWith("/")) { tempPath += directory; } else { if (ObjectUtil.isEmptyObject(tempPath)) { tempPath = directory; } else { tempPath = tempPath + "/" + directory; } } } sftp.cd(tempPath); } catch (SftpException e) { //目录不存在,则创建文件夹 String [] dirs= tempPath.split("/"); String path = ""; for(String dir : dirs){ if(ObjectUtil.isEmptyObject(dir)) continue; if (tempPath.startsWith("/")) { path += "/" + dir; } else { if (ObjectUtil.isEmptyObject(path)) { path += dir; } else { path += "/" + dir; } } try{ sftp.cd(path); }catch(SftpException ex){ sftp.mkdir(path); sftp.cd(path); } } } sftp.put(input, sftpFileName); //上传文件 this.logout(); return true; } /** * 下载文件 到 指定目录
* @param directory 下载目录
* @param downloadFile 下载的文件
* @param saveFile 存在本地的路径
*/
public boolean downloadFile(String directory, String downloadFile, String saveFile) throws SftpException, IOException { try { if (!ObjectUtil.isEmptyObject(directory)) { sftp.cd(directory); } saveFile = saveFile.replace("\\", File.separator); saveFile = saveFile + (saveFile.endsWith(File.separator) ? downloadFile : "/" + downloadFile); File file = file = new File(saveFile); if (file.exists()) { file.delete(); } file.createNewFile(); file = new File(saveFile); sftp.get(downloadFile, new FileOutputStream(file)); return true; } catch (Exception e) { e.printStackTrace(); throw e; } finally { this.logout(); } } /** * 下载文件,获取二进制数组
* @param directory 下载目录
* @param downloadFile 下载的文件名
* @return 字节数组
*/
public byte[] downloadFile(String directory, String downloadFile) throws SftpException, IOException{ try { if (!ObjectUtil.isEmptyObject(directory)) { sftp.cd(directory); } InputStream is = sftp.get(downloadFile); byte[] fileData = IOUtils.toByteArray(is); return fileData; } catch (Exception e) { e.printStackTrace(); throw e; } finally { this.logout(); } } /** * 删除文件
* @param directory 要删除文件所在目录
* @param deleteFile 要删除的文件
*/
public void deleteFile(String directory, String deleteFile) throws SftpException{ try { sftp.cd(directory); sftp.rm(deleteFile); } catch (SftpException e) { e.printStackTrace(); throw e; } finally { this.logout(); } } /** * 列出目录下的文件
* @param directory 要列出的目录
*/
public Vector<?> listFiles(String directory) throws SftpException { try { return sftp.ls(directory); } catch (SftpException e) { e.printStackTrace(); throw e; } finally { this.logout(); } } //上传文件测试 public static void main(String[] args) throws SftpException, IOException { SFTPUtil sftp = new SFTPUtil("ip",22,"用户名","密码"); sftp.login(); FileInputStream is =new FileInputStream(new File("F:\\abc\\哈哈.txt")); // sftp.uploadFile("","文件上传目录", "哈哈.txt", is); // sftp.downloadFile("文件所在目录", "哈哈.txt","F:/abc"); sftp.logout(); }

6. 判断空工具

import java.util.*;
/**
 * 字符串工具类
 */
public class ObjectUtil {
	/**
	 * 判断对象是否为空
	 * @Author: xiezb
	 * @param obj 对象
	 * @return 是否为空
	 */
	public static boolean isEmptyObject(Object obj) {
		return obj == null;
	}

	/**
	 * 判断哈希是否为空
	 * @Author: xiezb
	 * @param map 哈希
	 * @return 是否为空
	 */
	public static boolean isEmptyObject(Map<?, ?> map) {
		return (map == null || map.size() == 0);
	}

	/**
	 * 判断字符是否为空
	 * @Author: xiezb
	 * @param str 字符
	 * @return 是否为空
	 */
	public static boolean isEmptyObject(String str) {
		return (str == null || "".equals(str) || "null".equalsIgnoreCase(str) || str.trim().length() == 0);
	}

	/**
	 * 判断数组是否为空
	 * @Author: xiezb
	 * @param arr 数组
	 * @return 是否为空
	 */
	public static boolean isEmptyObject(Arrays[] arr) {
		return (arr == null || arr.length == 0);
	}

	/**
	 * 判断列表是否为空
	 * @Author: xiezb
	 * @param lis 列表
	 * @return 是否为空
	 */
	public static boolean isEmptyObject(List<?> lis) {
		return (lis == null || lis.size() == 0);
	}

	/**
	 * 判断集合是否为空
	 * @Author: xiezb
	 * @param ita 集合
	 * @return 是否为空
	 */
	public static boolean isEmptyObject(Iterator<?> ita) {
		return (ita == null || !ita.hasNext());
	}

	/**
	 * 判断缓存是否为空
	 * @Author: xiezb
	 * @param sbf 缓存
	 * @return 是否为空
	 */
	public static boolean isEmptyObject(StringBuffer sbf) {
		return (sbf == null || sbf.length() == 0);
	}

}
  • 到此, 可通过上面代码自行测试, 快动手试试吧

你可能感兴趣的:(java)