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

        

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容