用ftp连接方式会报SSH访问失败,改成sftp连接。这个SSH到底是啥呢?先做个解释说明:
是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境。SSH通过在网络中创建安全隧道来实现SSH客户端与服务器之间的连接
@Slf4j
public class FtpUtil {
@Value("${ftp.host}")
private String host;
@Value("${ftp.username}")
private String username;
@Value("${ftp.password}")
private String password;
private static String ftpFilePath = "/learning/weidai/data/document.js";
public static void main(String[] args) {
FtpUtil ftpUtil = new FtpUtil();
//下载文件
//ftpUtil.downLoadFile(ftpFilePath);
}
/**
* 建立连接,登录
* @return
*/
public FTPClient connectAndLogin(){
FTPClient ftpClient = new FTPClient();
try {
//连接服务器
ftpClient.connect(host,21);
//登录
boolean flag = ftpClient.login(username,password);
if(flag){
log.info("建立连接,登录ftp成功");
return ftpClient;
}else{
log.error("登录ftp失败");
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 退出登录,断开连接
* @param ftpClient
*/
public void logoutAndDisconnect(FTPClient ftpClient){
if(ftpClient!=null && ftpClient.isConnected()){
try {
//退出登录
ftpClient.logout();
//断开连接
ftpClient.disconnect();
System.out.println("退出登录,断开连接");
} catch (IOException e) {
e.printStackTrace();
}
}
}
/***
* 上传文件
*/
public void uploadFile(){
FtpUtil ftpUtil = new FtpUtil();
FTPClient ftpClient = ftpUtil.connectAndLogin();
if(ftpClient == null){
return;
}
//本地文件
File file = new File("file.pdf");
//将目录名称转为iso-8859-1编码 (FTP协议里面,规定文件名编码为iso-8859-1)
String validPath = new String(ftpFilePath.getBytes(), StandardCharsets.ISO_8859_1);
//文件上传到ftp的文件名
String fileName = "测试.txt";
// FTP协议里面,规定文件名编码为iso-8859-1
String ftpFileName = new String(fileName.getBytes(),StandardCharsets.ISO_8859_1);
//文件输入流 FileIntPutStream
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
//设置缓冲区大小 4M
ftpClient.setBufferSize(4*1024*1024);
//设置编码
ftpClient.setControlEncoding("utf-8");
boolean changeWorkDirFlag = ftpClient.changeWorkingDirectory(validPath);
if(!changeWorkDirFlag){
//创建子目录
createDirectory(ftpClient,validPath);
}
//存储文件至ftp服务器
boolean flag = ftpClient.storeFile(ftpFileName,fis);
System.out.println("上传文件"+(flag?"成功":"失败"));
} catch (Exception e) {
e.printStackTrace();
}finally {
ftpUtil.logoutAndDisconnect(ftpClient);
}
}
/**
*
* 在根目录下创建目录,我自己搭建的vsftp服务器根目录是/root,因此是在/root下创建目录
* @param ftpClient ftp客户端
* @param directory 文件目录,将在根目录下创建
*/
public void createDirectory(FTPClient ftpClient,String directory) {
String fileSeparator = "/";
if (!directory.endsWith(fileSeparator)) {
directory += fileSeparator;
}
int fromIndex = 0;
int endIndex = 0;
try {
if(ftpClient.changeWorkingDirectory(directory)){
//如果目录存在,直接返回
return;
}
if (directory.startsWith(fileSeparator)) {
fromIndex = 1;
}
endIndex = directory.indexOf(fileSeparator, fromIndex);
while (true) {
String subDirectory = new String(directory.substring(fromIndex, endIndex));
if (!ftpClient.changeWorkingDirectory(subDirectory)) {
if (ftpClient.makeDirectory(subDirectory)) {
ftpClient.changeWorkingDirectory(subDirectory);
} else {
System.out.println("创建"+subDirectory+"目录失败");
return;
}
}
fromIndex = endIndex + 1;
endIndex = directory.indexOf(fileSeparator, fromIndex);
//检查所有目录是否创建完毕
if (endIndex <= fromIndex) {
break;
}
}
System.out.println("上传目录创建成功");
} catch (Exception e) {
System.out.println("上传目录创建失败");
e.printStackTrace();
}
}
/**
* 下载文件
*/
public static byte[] downLoadFile(String filePath){
FtpUtil ftpUtil = new FtpUtil();
FTPClient ftpClient = ftpUtil.connectAndLogin();
if(ftpClient == null){
return null;
}
//ftp服务器文件名
String validFtpFilePath = new String(filePath.getBytes(),StandardCharsets.ISO_8859_1);
//下载到本地地址
String localPath = "file.pdf";
try {
OutputStream os = new FileOutputStream(localPath);
//1、检查文件是否存在
if(!isFileExist(filePath,ftpClient)){
log.info("文件不存在");
return null;
}
boolean flag = ftpClient.retrieveFile(validFtpFilePath,os);
log.info("下载文件"+(flag?"成功":"失败"));
//转换为byte流
FileInputStream fis = new FileInputStream(localPath);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int n;
while ((n = fis.read(b)) != -1)
{
bos.write(b, 0, n);
}
fis.close();
bos.close();
byte[] buffer = bos.toByteArray();
return buffer;
} catch (Exception e) {
e.printStackTrace();
}finally {
ftpUtil.logoutAndDisconnect(ftpClient);
}
return null;
}
/**
* 判断文件是否存在
* @param ftpFile
* @param ftpClient
* @return
*/
public static Boolean isFileExist(String ftpFile, FTPClient ftpClient) {
if (ftpClient != null) {
try {
String validFtpFile = new String(ftpFile.getBytes(),StandardCharsets.ISO_8859_1);
String path = validFtpFile.substring(0,validFtpFile.lastIndexOf("/"));
String fileName = validFtpFile.substring(validFtpFile.lastIndexOf("/")+1);
// 判断是否存在该目录
boolean changeWorkDirFlag = ftpClient.changeWorkingDirectory(path);
if (!changeWorkDirFlag) {
System.out.println("目录不存在");
return false;
}
ftpClient.enterLocalPassiveMode(); // 设置被动模式,开通一个端口来传输数据
String[] fs = ftpClient.listNames();
// 判断该目录下是否有文件
if (fs == null || fs.length == 0) {
System.out.println("该目录下没有文件");
return false;
}
for (String ftpName : fs) {
if (ftpName.equals(fileName)) {
return true;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
/**
* 删除文件
*/
public void deleteFile(){
FtpUtil ftpUtil = new FtpUtil();
FTPClient ftpClient = ftpUtil.connectAndLogin();
if(ftpClient == null){
return;
}
String fileName = "/root/ftp/测试目录/测试.txt";
String validFileName = new String(fileName.getBytes(), StandardCharsets.ISO_8859_1);
boolean flag ;
try {
flag = ftpClient.deleteFile(validFileName);
System.out.println("文件删除结果:"+flag);
} catch (IOException e) {
e.printStackTrace();
}finally {
ftpUtil.logoutAndDisconnect(ftpClient);
}
}
/**
* 写文件
*/
public void writeFile(){
FtpUtil ftpUtil = new FtpUtil();
FTPClient ftpClient = ftpUtil.connectAndLogin();
if(ftpClient == null){
return;
}
String content = "写入ftp服务器上文件内容";
String validFileName = new String(ftpFilePath.getBytes(),StandardCharsets.ISO_8859_1);
//将content转为输入流
ByteArrayInputStream is = new ByteArrayInputStream(content.getBytes());
try {
boolean flag = ftpClient.storeFile(validFileName,is);
System.out.println("写文件至ftp"+(flag?"成功":"失败"));
} catch (IOException e) {
e.printStackTrace();
}finally {
ftpUtil.logoutAndDisconnect(ftpClient);
}
}
/**
* 读文件
*/
public void readFile(){
FtpUtil ftpUtil = new FtpUtil();
FTPClient ftpClient = ftpUtil.connectAndLogin();
if(ftpClient == null){
return;
}
String validFileName = new String(ftpFilePath.getBytes(), StandardCharsets.ISO_8859_1);
try {
if(!isFileExist(ftpFilePath,ftpClient)){
System.out.println("文件不存在");
return;
}
InputStream inputStream = ftpClient.retrieveFileStream(validFileName);
//将输入流转为字符串
InputStreamReader reader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(reader);
String line;
System.out.println("读取文件内容为:");
while ((line = bufferedReader.readLine()) !=null){
//文件内容
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
ftpUtil.logoutAndDisconnect(ftpClient);
}
}
}
解决办法:
一般我们使用 Xftp 或 FileZilla这些软件去连接服务器(FTP/SFTP)都是可以连接到。区别就是连接的参数中
1.协议:ftp 或 sftp
2.端口:21/22
但是在Java后台使用org.apache.commons.net.ftp.FTPClient通过协议SSH2进行SFTP连接时就会报如上错误,原因是它不支持这种方式的连接(使用FTPSClient的SSL也是不行的)。
解决方法有两种:
第一种:Java后台继续使用org.apache.commons.net.ftp.FTPClient工具,然后把服务器开启FTP协议。
第二种:换一种连接方式,使用 com.jcraft.jsch.ChannelSftp 代替org.apache.commons.net.ftp.FTPClient。
<!-- sftp -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>@Slf4j
public class SftpUtil {
@Value("${ftp.host}")
private String server;
@Value("${ftp.username}")
private String loginName;
@Value("${ftp.password}")
private String loginPassword;
private Integer port = 22;
public static void main(String[] args) {
SftpUtil sftpUtil = new SftpUtil();
//上传文件
sftpUtil.uploadFile();
//下载文件
sftpUtil.downloadFile("目录/文件");
//写文件
sftpUtil.writeFile();
//读文件
sftpUtil.readFile();
//删除文件
sftpUtil.deleteFile();
}
/**
* 连接登陆远程服务器
*
* @return
*/
public ChannelSftp connect() {
JSch jSch = new JSch();
Session session = null;
ChannelSftp sftp = null;
try {
session = jSch.getSession(loginName, server, port);
session.setPassword(loginPassword);
session.setConfig(this.getSshConfig());
session.connect();
sftp = (ChannelSftp)session.openChannel("sftp");
sftp.connect();
log.error("结果:"+session.equals(sftp.getSession()));
log.info("登录成功:" + sftp.getServerVersion());
} catch (Exception e) {
log.error("SSH方式连接FTP服务器时有JSchException异常!",e);
return null;
}
return sftp;
}
/**
* 获取服务配置
* @return
*/
private Properties getSshConfig() {
Properties sshConfig = new Properties();
sshConfig.put("StrictHostKeyChecking", "no");
return sshConfig;
}
/**
* 关闭连接
* @param sftp
*/
public void disconnect(ChannelSftp sftp) {
try {
if(sftp!=null){
if(sftp.getSession().isConnected()){
sftp.getSession().disconnect();
}
}
} catch (Exception e) {
log.error("关闭与sftp服务器会话连接异常",e);
}
}
/**
* 下载远程sftp服务器文件
*
* @return
*/
public void downloadFile(String remoteFilename) {
FileOutputStream output = null;
ChannelSftp sftp = null;
try {
sftp = connect();
if(sftp == null){
return ;
}
//sftp服务器上文件路径
//String remoteFilename = "/test1/测试.txt";
//下载至本地路径
File localFile = new File("file.pdf");
output = new FileOutputStream(localFile);
sftp.get(remoteFilename, output);
System.out.println("成功接收文件,本地路径:" + localFile.getAbsolutePath());
} catch (Exception e) {
log.error("接收文件异常!",e);
} finally {
try {
if (null != output) {
output.flush();
output.close();
}
// 关闭连接
disconnect(sftp);
} catch (IOException e) {
log.error("关闭文件时出错!",e);
}
}
}
/**
* 读取远程sftp服务器文件
*
* @return
*/
public void readFile() {
InputStream in = null;
ArrayList<String> strings = new ArrayList<>();
ChannelSftp sftp = null;
try {
sftp = connect();
if(sftp == null){
return;
}
String remotePath = "/test1/";
String remoteFilename = "测试1.txt";
sftp.cd(remotePath);
if(!listFiles(remotePath).contains(remoteFilename)){
log.error("no such file");
return;
}
in = sftp.get(remoteFilename);
if (in != null) {
BufferedReader br = new BufferedReader(new InputStreamReader(in,"utf-8"));
String str = null;
while ((str = br.readLine()) != null) {
System.out.println(str);
}
}else{
log.error("in为空,不能读取。");
}
} catch (Exception e) {
log.error("接收文件时异常!",e);
} finally {
try {
if(in !=null){
in.close();
}
// 关闭连接
disconnect(sftp);
} catch (Exception e) {
log.error("关闭文件流时出现异常!",e);
}
}
}
/**
* 写文件至远程sftp服务器
*
* @return
*/
public void writeFile(){
ChannelSftp sftp = null;
ByteArrayInputStream input = null;
try {
sftp = connect();
if(sftp == null){
return;
}
// 更改服务器目录
String remotePath = "/test1/";
sftp.cd(remotePath);
// 发送文件
String remoteFilename = "写文件.txt";
String content = "测试内容";
input = new ByteArrayInputStream(content.getBytes());
sftp.put(input, remoteFilename);
} catch (Exception e) {
log.error("发送文件时有异常!",e);
} finally {
try {
if (null != input) {
input.close();
}
// 关闭连接
disconnect(sftp);
} catch (Exception e) {
log.error("关闭文件时出错!",e);
}
}
}
/**
* 上传文件至sftp服务器
* @return
*/
public void uploadFile() {
FileInputStream fis = null;
ChannelSftp sftp = null;
// 上传文件至服务器此目录
String remotePath = "./file/sftp/从sftp服务器上下载.txt";
String remoteFilename = "/test1/上传至sftp服务器.txt";
try {
sftp = connect();
if(sftp == null){
return ;
}
File localFile = new File(remotePath);
fis = new FileInputStream(localFile);
//发送文件
sftp.put(fis, remoteFilename);
log.info("成功上传文件" );
} catch (Exception e) {
log.error("上传文件时异常!",e);
} finally {
try {
if (fis != null) {
fis.close();
}
// 关闭连接
disconnect(sftp);
} catch (Exception e) {
log.error("关闭文件时出错!",e);
}
}
}
/**
* 遍历远程文件
*
* @param remotePath
* @return
* @throws Exception
*/
public List<String> listFiles(String remotePath){
List<String> ftpFileNameList = new ArrayList<String>();
ChannelSftp.LsEntry isEntity = null;
String fileName = null;
ChannelSftp sftp = null;
try{
sftp = connect();
if(sftp == null){
return null;
}
Vector<ChannelSftp.LsEntry> sftpFile = sftp.ls(remotePath);
Iterator<ChannelSftp.LsEntry> sftpFileNames = sftpFile.iterator();
while (sftpFileNames.hasNext()) {
isEntity = (ChannelSftp.LsEntry) sftpFileNames.next();
fileName = isEntity.getFilename();
ftpFileNameList.add(fileName);
}
return ftpFileNameList;
}catch (Exception e){
log.error("遍历查询sftp服务器上文件异常",e);
return null;
}finally {
disconnect(sftp);
}
}
/**
* 删除远程文件
* @return
*/
public void deleteFile() {
boolean success = false;
ChannelSftp sftp = null;
try {
sftp = connect();
if(sftp == null){
return;
}
String remotePath = "/test1/";
String remoteFilename = "limit.lua";
// 更改服务器目录
sftp.cd(remotePath);
//判断文件是否存在
if(listFiles(remotePath).contains(remoteFilename)){
// 删除文件
sftp.rm(remoteFilename);
log.info("删除远程文件" + remoteFilename + "成功!");
}
} catch (Exception e) {
log.error("删除文件时有异常!",e);
} finally {
// 关闭连接
disconnect(sftp);
}
}
}版权声明:本文为Sunshinejourney原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。