两种ftp使用java的实现方式 ,代码都已测试
第一种:Serv-U FTP
先决条件:
1、Serv-U FTP服务器搭建成功。
2、jar包需要:版本不限制
实现代码:
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;import javax.swing.*;
import java.io.*;
import java.net.SocketException;public class FtpUtil {private static FTPClient ftpClient = new FTPClient();/*** 获取FTPClient对象** @param ftpHost FTP主机服务器* @param ftpPassword FTP 登录密码* @param ftpUserName FTP登录用户名* @param ftpPort FTP端口 默认为21* @return*/public FTPClient getFTPClient(String ftpHost, String ftpUserName,String ftpPassword, int ftpPort) {try {ftpClient.connect(ftpHost, ftpPort);// 连接FTP服务器ftpClient.login(ftpUserName, ftpPassword);// 登陆FTP服务器if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {System.out.println("未连接到FTP,用户名或密码错误。");ftpClient.disconnect();} else {System.out.println("FTP连接成功。");}} catch (SocketException e) {e.printStackTrace();System.out.println("FTP的IP地址可能错误,请正确配置。");} catch (IOException e) {e.printStackTrace();System.out.println("FTP的端口错误,请正确配置。");}return ftpClient;}/*** 从FTP服务器下载文件* @param ftpPath FTP服务器中文件所在路径* @param localPath 下载到本地的位置* @param fileName 文件名称*/public void downloadFtpFile( String ftpPath, String localPath,String fileName) {try {ftpClient.setControlEncoding("UTF-8"); // 中文支持
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);ftpClient.enterLocalPassiveMode();ftpClient.changeWorkingDirectory(ftpPath);File localFile = new File(localPath + File.separatorChar + fileName);OutputStream os = new FileOutputStream(localFile);ftpClient.retrieveFile(fileName, os);os.close();ftpClient.logout();} catch (FileNotFoundException e) {System.out.println("没有找到" + ftpPath + "文件");e.printStackTrace();} catch (SocketException e) {System.out.println("连接FTP失败.");e.printStackTrace();} catch (IOException e) {e.printStackTrace();System.out.println("文件读取错误。");e.printStackTrace();}}/*** Description: 向FTP服务器上传文件* @param ftpPath FTP服务器中文件所在路径 格式: ftptest/aa* @param fileName ftp文件名称* @param input 文件流* @return 成功返回true,否则返回false*/public boolean uploadFile( String ftpPath,String fileName,InputStream input) {boolean success = false;try {int reply;reply = ftpClient.getReplyCode();if (!FTPReply.isPositiveCompletion(reply)) {ftpClient.disconnect();return success;}ftpClient.setControlEncoding("UTF-8"); // 中文支持
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);ftpClient.enterLocalPassiveMode();ftpClient.changeWorkingDirectory(ftpPath);ftpClient.storeFile(fileName, input);input.close();ftpClient.logout();success = true;} catch (IOException e) {e.printStackTrace();} finally {if (ftpClient.isConnected()) {try {ftpClient.disconnect();} catch (IOException ioe) {}}}return success;}public static void main(String args[]){String ftpHost = "127.0.0.1";String ftpUserName = "servUFtp";String ftpPassword = "14oioppii";Integer port = 21;String ftpPath = "/";String localPath = "F:\\";String fileName = "text.jpg";//上传一个文件try{FileInputStream in=new FileInputStream(new File(localPath));FtpUtil ftpUtil = new FtpUtil();ftpUtil.getFTPClient(ftpHost, ftpUserName, ftpPassword, port);// 上传文件boolean flag = ftpUtil.uploadFile( ftpPath, fileName,in);// 下载文件ftpUtil.downloadFtpFile( "/000.jpg", localPath, fileName);if(flag){System.out.println("文件上传ftp成功,请检查ftp服务器。");}else{System.out.println("文件上传ftp异常。请重试!");}} catch (FileNotFoundException e){e.printStackTrace();System.out.println(e);}}}
第二种:SFTP
先决条件:
1、SFTP服务器搭建成功
2、jar需要:版本不限
实现代码:
import com.jcraft.jsch.*;import java.io.*;
import java.util.Properties;/*** @Author : guoyanan* @Title : Sftp工具类* @Time : 2019/04/18 14:52* @Document : 提供文件上传功能*/
public class SFtpUtils {// 初始化单例对象private static SFtpUtils sFtpUtils = new SFtpUtils();private String host;//服务器连接ipprivate String username;//用户名private String password;//密码private int port = 22;//端口号private ChannelSftp sftp = null;private Session sshSession = null;/*** 初始化sftp的单例对象* @return*/public static SFtpUtils getInstance(){return sFtpUtils;}/*** 初始化sft链接信息,必须先做这个* @param host 远程主机ip* @param port 端口号* @param username 账号* @param password 密码*/public void init(String host, int port, String username, String password){this.host = host;this.username = username;this.password = password;this.port = port;}/*** 通过SFTP连接服务器*/public void connect(){try{JSch jsch = new JSch();jsch.getSession(username, host, port);sshSession = jsch.getSession(username, host, port);sshSession.setPassword(password);Properties sshConfig = new Properties();sshConfig.put("StrictHostKeyChecking", "no");sshSession.setConfig(sshConfig);sshSession.connect();Channel channel = sshSession.openChannel("sftp");channel.connect();sftp = (ChannelSftp) channel;}catch (Exception e){e.printStackTrace();}}/*** 关闭连接*/public void disconnect(){if (this.sftp != null){if (this.sftp.isConnected()){this.sftp.disconnect();}}if (this.sshSession != null){if (this.sshSession.isConnected()){this.sshSession.disconnect();}}}/*** sftp下载文件* @param remoteFielPath 远程文件路径* @param localFilePath 本地下载路径* @return* @throws SftpException* @throws FileNotFoundException*/public boolean downLoadFile(String remoteFielPath,String localFilePath) throws SftpException, FileNotFoundException {// 检查文件是否存在SftpATTRS sftpATTRS = sftp.lstat(remoteFielPath);if(!sftpATTRS.isReg()){// 不是一个文件,返回falsereturn false;}// 下载文件到本地
sftp.get(remoteFielPath,localFilePath);return true;}/*** 下载文件放回文件数据* @param remoteFielPath* @return* @throws SftpException* @throws IOException*/public boolean downLoadFileTwo(String remoteFielPath, String localFilePath) throws SftpException, IOException {// 检查文件是否存在SftpATTRS sftpATTRS = sftp.lstat(remoteFielPath);// 判断是否是一个文件if(sftpATTRS.isReg()){// 下载文件到本地InputStream inputStream = sftp.get(remoteFielPath);/**今天想写下从sftp下载文件到本地,虽然sftp提供了get(String remotePath,String LocalPath)方法,将远程文件写入到本地。* 但还是想属性下从远程获取InputStream对象写入到本地的方式。* 遇到的问题:刚开始只想这实现,就是获取byte对象写入到本地文件,先用ByteArrayInputStream怎么转都无法获取到bytes对象* 放入到FileOutputStream对象中。搞了老半天都没有搞定,或许有ByteArrayInputStream对象下载的方式但没有找到。* 正解:如下*/// 通过BufferedInputStream对象缓存输入流对象获取远程的输入流BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);// 创建本地文件信息File file = new File("F:\\456.jpg");// 将本地文件放入到 本地文件输出流FileOutputStream fileOutputStream = new FileOutputStream(file);// 将本地文件输出流 放入到 缓存输出流对象BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);// 声明每次获取的byte长度int len = 2048;// 初始化byte[]byte[] bytes = new byte[len];/**通过BufferedInputStream对象获取 远程文件 InputStream的bytes字节信息,并循环添加到BufferedOutputStream缓存输出流对象中,* 将远程bytes数据写入到本地文件中* 遇到的问题:这里我一直纠结于为什么这样写会实现想要的效果,是如何写入到本地的* 其实这不是开发中遇到的问题的事情了,是自己困于自己设定的一个纠结情绪中了。也就是俗称的牛角尖。* 切记,一定不可以钻牛角尖。因为开发都是有语言规则的。按照规则来就能实现效果,脱离规则即使神仙也无能为力。* */while ((len = bufferedInputStream.read(bytes)) != -1){bufferedOutputStream.write(bytes,0,len);}bufferedOutputStream.flush();bufferedInputStream.close();bufferedOutputStream.close();fileOutputStream.close();inputStream.close();return true;}return false;}/*** 上传单个文件,通过文件路径上传* @param remotePath:远程保存目录* @param remoteFileName:保存文件名* @param localPath:本地上传目录(以路径符号结束)* @param localFileName:上传的文件名* @return*/public boolean uploadFile(String remotePath, String remoteFileName,String localPath, String localFileName){FileInputStream in = null;try{ // 创建目录
createDir(remotePath);File file = new File(localPath + localFileName);in = new FileInputStream(file);sftp.put(in, remoteFileName);return true;}catch (FileNotFoundException e){e.printStackTrace();}catch (SftpException e){e.printStackTrace();}finally{if (in != null){try{in.close();}catch (IOException e){e.printStackTrace();}}}return false;}/*** 上传文件到sftp,通过输入流上传* @param remotePath* @param remoteFileName* @param inputStream* @return*/public boolean uploadFile(String remotePath, String remoteFileName,InputStream inputStream){FileInputStream in = null;try{ // 创建目录
createDir(remotePath);sftp.put(inputStream, remoteFileName);return true;}catch (SftpException e){e.printStackTrace();}finally{if (in != null){try{in.close();}catch (IOException e){e.printStackTrace();}}}return false;}/*** 创建目录* @param createpath* @return*/public boolean createDir(String createpath){try{if (isDirExist(createpath)){// 有时候,开发在填写路径的时候第一个位置会忘记加"/"的根路径// 这回引发cd操作是发生:NO Such File 异常,所以这里处理下if(!(createpath.substring(0,1)=="/")){createpath="/"+createpath;}this.sftp.cd(createpath);return true;}String pathArry[] = createpath.split("/");StringBuffer filePath = new StringBuffer("/");for (String path : pathArry){if (path.equals("")){continue;}filePath.append(path + "/");if (isDirExist(filePath.toString())){sftp.cd(filePath.toString());}else{// 建立目录
sftp.mkdir(filePath.toString());// 进入并设置为当前目录
sftp.cd(filePath.toString());}}this.sftp.cd(createpath);return true;}catch (SftpException e){e.printStackTrace();}return false;}/*** 判断目录是否存在,linux目录必须最前方带有"/"* @param directory* @return*/public boolean isDirExist(String directory){boolean isDirExistFlag = false;try{// 有时候,开发在填写路径的时候第一个位置会忘记加"/"的根路径// 这回引发cd操作是发生:NO Such File 异常,所以这里处理下if(!(directory.substring(0,1)=="/")){directory="/"+directory;}SftpATTRS sftpATTRS = sftp.lstat(directory);isDirExistFlag = true;return sftpATTRS.isDir();}catch (Exception e){if (e.getMessage().toLowerCase().equals("no such file")){isDirExistFlag = false;}}return isDirExistFlag;}public static void main(String arg[]) throws IOException, SftpException {// 获取图片的InputStream对象,并将图片生成到sftp上SFtpUtils sFtpUtils= SFtpUtils.getInstance();sFtpUtils.init("127.0.0.1",22, "sftpuser", "UIOPOopi");sFtpUtils.connect();// 上传文件/*File file = new File("F:\\OK.jpg");InputStream in = new FileInputStream(file);boolean flag = sFtpUtils.uploadFile("/app/xwapp/Test","1111.jpg",in);*/// 下载文件到本地方法1// boolean flag = sFtpUtils.downLoadFile("/app/xwapp/Test/1111.jpg","F:\\OKbak.jpg");// 下载文件到本地方法2boolean flag = sFtpUtils.downLoadFileTwo("/app/xwapp/Test/1111.jpg","F:\\OKbak.jpg");if(flag){System.out.println("处理成功");}else {System.out.println("处理失败");}sFtpUtils.disconnect();}
}