android 请求sftp服务器

        最近的项目上需要访问客户的sftp服务器,开发文件的上传和下载的功能,上网查询了相关知识点,中间也踩过不少坑,学到蛮多东西。

        参考链接:https://www.jianshu.com/p/05341634bae2

                          https://blog.csdn.net/ruixue0117/article/details/86517566

    1. 使用ftpClient进行处理

        刚开始在http的相关jar包中去找,发现android并没有官方提供的api方法调用,需要添加第三方jar包,这其中使用较多的就是 ftp4j 和common-net的包,后者属于java的基础包之一。这里我选择的是common-net的包,于是上网去查询,发现好多包的版本不一,而且都是需要积分的。这个时候突然想起,这种包应该在maven仓库中会有引入地址的。但是我突然忘记了maven官网的地址,这里安利一个网站叫 https://www.wanandroid.com/ 很适合学习安卓的小伙伴,我在这的入口找到了common-net的引用地址。

jar包地址

        在gradle中添加远程依赖 implementation 'commons-net:commons-net:3.7.2',其中关键的一个类就是FtpClient,这个类中封装了请求ftp服务器的方法。具体使用过程可以参靠https://www.jianshu.com/p/05341634bae2,当我按照这个方法进行调试时,发现请求连接服务器失败,报错信息为 org.apache.commons.net.MalformedServerReplyException: Could not parse response code.Server Reply: SSH-2.0-OpenSSH_5.3 ,查询资料后得知,当使用org.apache.commons.net.ftp.FTPClient通过协议SSH2进行SFTP连接时报如上错误,原因是它不支持这种方式的连接(使用FTPSClient的SSL也是不行的)。

2. 使用jsch访问sftp服务器

        common-net的包提供的方法不行,考虑是不是因为功能上有差异,于是转为使用ftp4j的jar包,引入方式也是采用gradle配置,引入之后发现核心处理类依旧是ftpclient,只是封装方式跟common-net有一些区别而已,既然是协议方面的问题,于是跟客户沟通发现其开通了sftp服务协议,那现在就应该是sftp的服务器了,那就不能用最基本的请求ftp的方法来处理 ,这里我使用的com.jcraft.jsch.JSch的类来进行处理。

    首先依旧是引入远程仓库地址 implementation'com.jcraft:jsch:0.1.55'  ,接下来便是封装相关的工具类,这里我把代码放上来,很简单的代码。

private JSchjSch;     

private Sessionsession =null;

private ChannelSftpsftp =null;

private SessionsshSession =null;

private static SftpUtilssftpUtils =null;

public SftpUtils() {

jSch =new JSch();

}

public static SftpUtilsgetInstance(){

if (sftpUtils==null){

sftpUtils =new SftpUtils();

  }

return  sftpUtils;

}

/*

* 启动连接

* */

public void connect(){

try {

jSch.getSession(Constant.FTP_USERNAME,Constant.FTP_URL,22);

    sshSession =jSch.getSession(Constant.FTP_USERNAME,Constant.FTP_URL,22);

    sshSession.setPassword(Constant.FTP_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 (JSchException 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();

    }

}

}

/*

* 批量下载文件

* */

public ListbatchDownFile(){

List filenames =new ArrayList();//本地已更新文件的路径集合

  String saveStoreFileName = SharedHelp.getString("saveStoreFileName","");

  String saveProductFileName = SharedHelp.getString("saveProductFileName","");

  boolean _flag =false;

  if (!isConnect()){

connect();

    _flag =true;

  }

try {

Vector v = listFiles("inbound");

    if (v.size()>0){

Iterator iterator = v.iterator();

      while (iterator.hasNext()){

ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) iterator.next();

        SftpATTRS attrs = entry.getAttrs();

        if (!attrs.isDir()){

boolean flag =false;

          String filename = entry.getFilename();

          if (filename.contains("store_fixture") && !filename.equals(saveStoreFileName) ){

//ftp服务器上的文件跟本地文件不一致,启动更新

            String localFilePath = CommonUtils.getLocalFilePath(Constant.LOCAL_FILE_INBODUN)

+ File.separator + filename;

              flag = downloadFile(Constant.FTP_FILE_DOWNLOAD_PATH,filename,localFilePath);

              if (flag){

SharedHelp.saveString("saveStoreFileName",filename);

                filenames.add(localFilePath);

              }

}else if(filename.contains("stock_sku_loc") && !filename.equals(saveProductFileName)){

String localFilePath = CommonUtils.getLocalFilePath(Constant.LOCAL_FILE_INBODUN)

+ File.separator + filename;

            flag = downloadFile(Constant.FTP_FILE_DOWNLOAD_PATH,filename, localFilePath);

            if (flag){

SharedHelp.saveString("saveProductFileName",filename);

              filenames.add(localFilePath);

            }

}

}

}

}

}catch (SftpException e) {

e.printStackTrace();

  }finally {

if (_flag)

disConnect();

  }

return filenames;

}

/*

* 下载单个文件

* */

public BooleandownloadFile(String remotePath,String remoteFileName,String localFilePath){

FileOutputStream fieloutput =null;

  boolean _flag =false;

  try {

if (!isConnect()){

connect();

      _flag =true;

    }

File file =new File(localFilePath);

    if (!file.exists()) {

File dir =new File(file.getParent());

      dir.mkdirs();

      file.createNewFile();

    }

fieloutput =new FileOutputStream(file);

    sftp.get(remotePath + File.separator + remoteFileName, fieloutput);

return true;

  }catch (Exception e) {

e.printStackTrace();

  }finally {

if (null != fieloutput) {

try {

fieloutput.close();

      }catch (IOException e) {

e.printStackTrace();

      }

}

if (_flag)

disConnect();

  }

return false;

}

/**

* 上传单个文件

*

* @param remotePath:远程保存目录

* @param remoteFileName:保存文件名

* @return

*/

public boolean uploadFile(FileInputStream fip, String remoteFileName, String remotePath) {

boolean _flag =false;

  try {

if (!isConnect()){

connect();

      _flag =true;

    }

createDir(remotePath);

    sftp.put(fip, remoteFileName);

return true;

  }catch (SftpException e) {

e.printStackTrace();

  }finally {

if (fip !=null) {

try {

fip.close();

      }catch (IOException e) {

e.printStackTrace();

      }

}

if (_flag)

disConnect();

  }

return false;

}

/**

* 创建目录

*

* @param createpath

* @return

*/

public boolean createDir(String createpath) {

boolean _flag =false;

  try {

if (!isConnect()){

connect();

      _flag =true;

    }

if (isDirExist(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();

  }finally {

if (_flag)

disConnect();

  }

return false;

}

/**

* 判断目录是否存在

*

* @param directory

* @return

*/

public boolean isDirExist(String directory) {

boolean isDirExistFlag =false;

  boolean _flag =false;

  try {

if (!isConnect()){

connect();

      _flag =true;

    }

SftpATTRS sftpATTRS =sftp.lstat(directory);

    isDirExistFlag =true;

    return sftpATTRS.isDir();

  }catch (Exception e) {

if (e.getMessage().toLowerCase().equals("no such file")) {

isDirExistFlag =false;

    }

}finally {

if (_flag)

disConnect();

  }

return isDirExistFlag;

}

/**

* 列出目录下的文件

*

* @param directory:要列出的目录

* @return

* @throws SftpException

*/

public VectorlistFiles(String directory)throws SftpException {

boolean _flag =false;

  if (!isConnect()){

connect();

    _flag =true;

  }

Vector ls =sftp.ls("/home/sftp/stockcount/" + directory);

  if (_flag)

disConnect();

  return ls;

}

public boolean isConnect() {

return (this.sftp !=null &&

this.sftp.isConnected() &&

this.sshSession !=null &&

this.sshSession.isConnected());

}

其中Constant类引用的静态对象是一些服务器地址  用户名  密码等配置。建议开发此功能之前先在电脑上下载查看ftp服务器的客户端应用。这样调试数据比较方便,也方便验证功能是否完善。网上很多工具,我这里使用的是xftp7,使用起来很方便。

xftp

        

你可能感兴趣的:(android 请求sftp服务器)