一、前言

最近在项目中遇到使用到FTP上传和下载资源,特此记录一下实现的方式。Android实现FTP的功能主要用到了Apache的Commons Net库,将Commons Net的jar包下载引入到项目中即可。
基本使用流程图如下:

二、基本实现

2.1 连接和登录

FTP协议和HTTP协议有所不同,使用FTP进行下载时,你需要进行登录操作。如果服务器没设置登录功能可忽略登录操作。

    /*** 连接到FTP服务器** @param host     ftp服务器域名* @param username 访问用户名* @param password 访问密码* @param port     端口* @param enterLocalPassiveMode 被动模式开关 如果不开被动模式 有防火墙 可能会上传失败, 但被动模式需要ftp支持*/private fun ftpConnect(host: String,port: Int,username: String?,password: String?,enterLocalPassiveMode:Boolean = true): FTPClient {val ftpClient = FTPClient()try {//设置超时时间以毫秒为单位使用时,从数据连接读。ftpClient.defaultTimeout = 10000ftpClient.connectTimeout = 10000ftpClient.setDataTimeout(10000)Log.d(TAG, "connecting to the ftp server $host:$port")//连接到FTP服务器ftpClient.connect(host, port)ftpClient.login(username, password)//是否开启被动模式if (enterLocalPassiveMode) {ftpClient.isRemoteVerificationEnabled = falseftpClient.enterLocalPassiveMode()}//请求使用UTF-8编码ftpClient.controlEncoding = "utf-8"val reply: Int = ftpClient.replyCodeif (!FTPReply.isPositiveCompletion(reply)) {ftpClient.disconnect()Log.e(TAG, "无法连接到ftp服务器,错误码为:$reply")} else {Log.d(TAG, "连接到ftp服务器")}} catch (e: Exception) {e.printStackTrace()Log.e(TAG, "Error: could not connect to host $host")}return ftpClient}

注意:由于FTP服务器默认的编码是ISO-8859-1,因此,客户端在获取文件信息时需要请求服务器使用UTF-8编码(如果服务器支持的话),如果服务器不支持开启UTF-8编码,那么客户端在请求remotePath路径、获取文件名时,都需要对路径进行编码转换处理。

2.2 断开连接

    /*** 断开ftp服务器连接** @return 断开结果*/private fun ftpDisconnect(ftpClient: FTPClient?) {// 判断空指针if (ftpClient == null) {return}// 断开ftp服务器连接try {ftpClient.logout()ftpClient.disconnect()Log.d(TAG, "断开连接")} catch (e: Exception) {Log.e(TAG, "Error occurred while disconnecting from ftp server.")}}

注意:在下载或上传资源时首先要连接服务器,在完成操作后要记得断开连接。

2.3 上传文件

    /*** 上传文件(直接读取输入流形式)** @param ftpSavePath       ftp服务保存地址* @param ftpSaveFileName  上传到ftp的文件名* @param inputStream      输入文件流* @return*/fun uploadFile(host: String,port: Int,username: String?,password: String?,ftpSavePath: String,ftpSaveFileName: String,inputStream: InputStream): Boolean {val ftpClient = ftpConnect(host, port, username, password)var flag = falsetry {val pathName = if (ftpSavePath.endsWith("/"))"$ftpSavePath$ftpSaveFileName"else"$ftpSavePath/$ftpSaveFileName"Log.i(TAG, """上传文件的路径 :$pathName开始上传文件...""".trimIndent())//设置文件类型ftpClient.setFileType(FTP.BINARY_FILE_TYPE)flag = ftpClient.storeFile(String(pathName.toByteArray(), Charsets.ISO_8859_1),inputStream)inputStream.close()} catch (e: Exception) {Log.e(TAG, e.toString())} finally {Log.i(TAG, "$ftpSaveFileName 文件上传 :" + if (flag) "成功" else "失败 ")try {inputStream.close()} catch (e: IOException) {Log.e(TAG, e.toString())} finally {ftpDisconnect(ftpClient)}}return flag}

注意:如果服务器不支持UTF-8编码,则要按上面的String(pathName.toByteArray(), Charsets.ISO_8859_1)的写法,进行编码转换处理,不然中文会乱码。如果支持UTF-8编码,则直接使用中文字符。

2.4 下载文件

    /*** 下载文件** @param pathName  FTP服务器文件目录 ** @param localPath 下载后的文件路径 ** @return*/fun downloadFile(host: String,port: Int,username: String?,password: String?,pathName: String,localPath: String): Boolean {val ftpClient = ftpConnect(host, port, username, password)var flag = falsevar outputStream: OutputStream? = nulltry {Log.i(TAG, """下载文件的路径 :$pathName 开始下载文件...""".trimIndent())ftpClient.setFileType(FTP.BINARY_FILE_TYPE)createLocalDirectory(localPath)outputStream = FileOutputStream(File(localPath))// 下载文件flag = ftpClient.retrieveFile(String(pathName.toByteArray(), Charsets.ISO_8859_1),outputStream)outputStream.close()} catch (e: Exception) {Log.e(TAG, e.toString())} finally {Log.i(TAG, "$pathName 文件 :" + if (flag) "成功" else "失败 ")if (null != outputStream) {try {outputStream.close()} catch (e: IOException) {Log.e(TAG, e.toString())} finally {ftpDisconnect(ftpClient)}}}return flag}//创建本地多层目录文件,如果已存在该文件,则不创建,如果无,则创建@Throws(IOException::class)private fun createLocalDirectory(localPath: String) {val path = localPath.substringBeforeLast("/")val file = File(path)if (!file.exists()) {file.mkdirs()}}

三、其他操作

为了安全,服务器可能只给了上传和下载的权限,也有可能给了其他操作权限,如删除文件、新建目录等。

3.1 创建目录

    /*** 创建多层目录文件,如果有ftp服务器已存在该文件,则不创建,如果无,则创建*/@Throws(IOException::class)fun createDirectory(host: String,port: Int,username: String?,password: String?,remote: String): Boolean {val ftpClient = ftpConnect(host, port, username, password)var flag = trueval directory = remote.substring(0, remote.lastIndexOf("/") + 1)if (!directory.equals("/", ignoreCase = true) &&!ftpClient.changeWorkingDirectory(String(directory.toByteArray(), Charsets.ISO_8859_1))) {// 如果远程目录不存在,则递归创建远程服务器目录var start = 0var end = 0start = if (directory.startsWith("/")) {1} else {0}end = directory.indexOf("/", start)while (true) {val subDirectory = String(remote.substring(start, end).toByteArray(), Charsets.ISO_8859_1)if (!ftpClient.changeWorkingDirectory(subDirectory)) {if (ftpClient.makeDirectory(subDirectory)) {ftpClient.changeWorkingDirectory(subDirectory)} else {flag = false}}start = end + 1end = directory.indexOf("/", start)// 检查所有目录是否创建完毕if (end <= start) {break}}}Log.i(TAG, "$remote 文件创建 :" + if (flag) "成功" else "失败 ")ftpDisconnect(ftpClient)return flag}

3.2 删除文件

    /*** 删除文件或文件夹*/fun deleteFile(host: String,port: Int,username: String?,password: String?,serverPath: String): Boolean {val ftpClient = ftpConnect(host, port, username, password)val flag = deleteFile(ftpClient, serverPath)Log.i(TAG, "$serverPath 文件删除 :" + if (flag) "成功" else "失败 ")ftpDisconnect(ftpClient)return flag}/*** 删除文件*/private fun deleteFile(ftpClient: FTPClient, pathName: String): Boolean {try {val files = ftpClient.listFiles(pathName)if (files.isNotEmpty()) {for (file in files) {if (file.isDirectory) {deleteFile(ftpClient, pathName + "/" + file.name)// 切换到父目录,不然删不掉文件夹ftpClient.changeWorkingDirectory(pathName.substring(0,pathName.lastIndexOf("/")))ftpClient.removeDirectory(pathName)} else {if (!ftpClient.deleteFile(pathName + "/" + file.name)) {return false}}}}// 切换到父目录,不然删不掉文件夹ftpClient.changeWorkingDirectory(pathName.substring(0, pathName.lastIndexOf("/")))ftpClient.removeDirectory(pathName)} catch (e: IOException) {e.printStackTrace()}return true}

Android 使用FTP实现上传、下载等功能相关推荐

  1. android ftp同步程序,ftp同步 安卓,安卓手机ftp上传下载文件功能同步视频照片

    手机拍照越来方便,手机里的照片也越积越多,手机运行缓慢,本文利用安卓的每步FTP服务APP来自动实现手机视频照片的同步,释放手机被占用的存储空间.在机顶盒上运行每步FTP服务,机顶盒USB口连接U盘做 ...

  2. Linux 终端访问 FTP 及 上传下载 文件

    今天同事问我一个问题,在Linux 下访问FTP,并将文件上传上去. 我之前一直是用WinSCP工具的. 先将文件从linux copy到windows下,然后在传到ftp上. google 一下. ...

  3. Linux 终端訪问 FTP 及 上传下载 文件

    今天同事问我一个问题,在Linux 下訪问FTP,并将文件上传上去. 我之前一直是用WinSCP工具的. 先将文件从linux copy到windows下,然后在传到ftp上. google 一下. ...

  4. java ftp 下载慢_Java实现ftp文件上传下载解决慢中文乱码多个文件下载等问题

    废话不多说了,直接给大家贴代码了,具体代码如下所示: //文件上传 public static boolean uploadToFTP(String url,int port,String usern ...

  5. ftp文件推送 linux_Linux 终端访问 FTP 及 上传下载 文件

    今天同事问我一个问题,在Linux 下访问FTP,并将文件上传上去. 我之前一直是用WinSCP工具的. 先将文件从linux copy到windows下,然后在传到ftp上.google 一下. 方 ...

  6. 关于FileZilla连接FTP站点上传下载文件

    关于FileZilla连接FTP站点上传下载文件 浏览器搜索FileZilla官网:https://www.filezilla.cn/download 根据自己操作系统安装 安装完成之后的启动界面是这 ...

  7. C++:FTP文件上传下载(附完整源码)

    C++:FTP文件上传下载 FTP文件下载 FTP文件上传 FTP文件下载 #include #include #include #pragma comment(lib, "WinInet. ...

  8. Android FTP 客户端 上传/下载 带进度条实战源码

    Android FTP 开发,我个人是使用commons-net-3.1.jar,别问我为什么是度娘教我的,附上commons-net-3.1.jar的开源下载地址http://grepcode.co ...

  9. [转]文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等)实现汇总1

    转自:http://blog.csdn.net/soarheaven/archive/2008/12/08/3474152.aspx 最近项目需要对FTP服务器进行操作,现把实现总结如下: 打算分2篇 ...

  10. Java通过FTP服务器上传下载文件的方法

    本文介绍了如何使用Apache Jakarta Commons Net(commons-net-3.3.jar)基于FileZilla Server服务器实现FTP服务器上文件的上传/下载/删除等操作 ...

最新文章

  1. 带你用深度学习虚拟机进行文本迁移学习(附代码)
  2. 实现计算机界“大满贯”,芮勇博士再获技术成就大奖
  3. windows下忘记mysql超级管理员密码的解决办法
  4. python常用函数import_python 常用函数集合
  5. 源码分析参考:Spider
  6. 拼多多股价创历史新高:市值再度逼近京东
  7. 【操作系统】—进程同步和进程互斥
  8. 工具类与工具函数 —— 素数相关
  9. Center OS7网络设置
  10. linux更改库文件vfp,VFP数据库修改与删除的基本操作
  11. linux查看二进制文件乱码
  12. dwg格式的计算机图,看图纸(DWG文件浏览器)
  13. uygurqa输入法android,uygurqa维语输入法2021
  14. 比较(0,π/2]上对sinx/x的定积分、对x/sinx的定积分与1的大小关系
  15. WiFi产品的一般射频电路设计
  16. 企业网络安全 8 条实用参考
  17. Edison:FL Studio中的常用音频录制与剪辑插件
  18. html模仿 商城 静态页面,HTML+CSS简单实现凡客商城静态网页
  19. 海思AI芯片(Hi35XX): 图像jpg转.bgr
  20. PMP杂谈--快速记忆ITTO

热门文章

  1. 分销小程序功能有哪些?如何使用分销小程序实现裂变卖货?
  2. 苏嵌//张朋//2018.07.23
  3. 读吴军老师的《浪潮之巅》总结
  4. GrabCut python实现
  5. 牛掰了!鸿蒙与Android完美融合,将鸿蒙设备当Android设备用
  6. 电脑的CPU主频1.8GHZ够不够用
  7. 零基础入门Jetson Nano——软件篇
  8. 某公司HP-EVA4400存储硬盘离线的数据恢复方法和数据恢复过程
  9. MemCache详解
  10. FFmpeg进阶: 截取视频生成gif动图