Android局域网实现FTP文件上传下载客户端与服务端
生活随笔
收集整理的這篇文章主要介紹了
Android局域网实现FTP文件上传下载客户端与服务端
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 前言
- 一、FTP是什么?
- 二、使用步驟
- 1 服務端
- 1.1 服務端的代碼實現
- 2 客戶端
- 2.1 客戶端的代碼實現
- 附件
前言
最近在公司的項目中,使用到了 局域網通信,不同的設備直接傳遞消息以及發送文件。普通文本消息的發送使用websocket 封裝了一套可以使用,但是對于文件類型的消息,尤其是大文件的發送,使用websocket 發送字節數組的形式出現了很多的問題,所以就取消了使用websocket 自己封裝發送的方式。采用局域網
一、FTP是什么?
FTP(File Transfer Protocol,文件傳輸協議) 是 TCP/IP 協議組中的協議之一。FTP協議包括兩個組成部分,其一為FTP服務器,其二為FTP客戶端。
其中FTP服務器用來存儲文件,用戶可以使用FTP客戶端通過FTP協議訪問位于FTP服務器上的資源。在開發網站的時候,通常利用FTP協議把網頁或程序傳到Web服務器上。此外,由于FTP傳輸效率非常高,在網絡上傳輸大的文件時,一般也采用該協議
二、使用步驟
1 服務端
引入庫:
//ftp serverimplementation files('libs/ftpserver-core-1.0.6.jar')implementation files('libs/mina-core-2.0.16.jar')implementation 'commons-net:commons-net:3.8.0'1.1 服務端的代碼實現
FtpServerlet:
import androidx.annotation.Keep import org.apache.ftpserver.FtpServer import java.io.File import org.apache.ftpserver.listener.ListenerFactoryimport org.apache.ftpserver.FtpServerFactory import org.apache.ftpserver.ftplet.* import org.apache.ftpserver.usermanager.SaltedPasswordEncryptorimport org.apache.ftpserver.usermanager.PropertiesUserManagerFactory import org.apache.ftpserver.usermanager.impl.WritePermission import org.apache.ftpserver.usermanager.impl.BaseUser@Keep class FtpServerlet(private val sharedDirectory: String,private val ftpPort: Int = 2121,private val log: ((tag: String, content: String?) -> Unit)?=null ) :DefaultFtplet() {private val TAG = "FtpServerlet"private var mFtpServer: FtpServer? = nullprivate val mUser = "myUser"private val mPassword = "myPassword"fun startFtp() {if (null != mFtpServer && !mFtpServer!!.isStopped) {return}val file = File(sharedDirectory)if (!file.exists()) {file.mkdirs()}val serverFactory = FtpServerFactory()val listenerFactory = ListenerFactory()// 設定端末番號listenerFactory.port = ftpPort// 通過PropertiesUserManagerFactory創建UserManager然后向配置文件添加用戶val userManagerFactory = PropertiesUserManagerFactory()userManagerFactory.passwordEncryptor = SaltedPasswordEncryptor()val userManager: UserManager = userManagerFactory.createUserManager()val auths = mutableListOf<Authority>()val auth: Authority = WritePermission()auths.add(auth)//添加用戶val user = BaseUser()user.name = mUseruser.password = mPassworduser.homeDirectory = sharedDirectoryuser.authorities = authsuserManager.save(user)// 設定Ftpletval ftpletMap = mutableMapOf<String, Ftplet>()ftpletMap["Ftplet"] = thisserverFactory.userManager = userManager;serverFactory.addListener("default", listenerFactory.createListener()); // serverFactory.ftplets = ftpletMapmFtpServer = serverFactory.createServer();mFtpServer?.start()log?.invoke(TAG, "start ftp server , sharedDirectory = $sharedDirectory")}fun stopFtp() {// FtpServer不存在和FtpServer正在運行中if (null != mFtpServer && !mFtpServer!!.isStopped) {mFtpServer?.stop()log?.invoke(TAG, "stop ftp server")}}override fun onAppendStart(session: FtpSession?, request: FtpRequest?): FtpletResult {log?.invoke(TAG,"onAppendStart argument = ${request?.argument} , requestLine = ${request?.requestLine} , command = ${request?.command}")return super.onAppendStart(session, request)}override fun onAppendEnd(session: FtpSession?, request: FtpRequest?): FtpletResult {log?.invoke(TAG,"onAppendEnd argument = ${request?.argument} , requestLine = ${request?.requestLine} , command = ${request?.command}")return super.onAppendEnd(session, request)}override fun onLogin(session: FtpSession?, request: FtpRequest?): FtpletResult {log?.invoke(TAG, "onLogin argument = ${request?.argument} , requestLine = ${request?.requestLine} , command = ${request?.command}")return super.onLogin(session, request)}override fun onConnect(session: FtpSession?): FtpletResult {log?.invoke(TAG, "onConnect ")return super.onConnect(session)}override fun onDisconnect(session: FtpSession?): FtpletResult {log?.invoke(TAG, "onDisconnect ")return super.onDisconnect(session)}override fun onUploadStart(session: FtpSession?, request: FtpRequest?): FtpletResult {log?.invoke(TAG,"onUploadStart argument = ${request?.argument} , requestLine = ${request?.requestLine} , command = ${request?.command}")return super.onUploadStart(session, request)}override fun onUploadEnd(session: FtpSession?, request: FtpRequest?): FtpletResult {log?.invoke(TAG,"onUploadEnd argument = ${request?.argument} , requestLine = ${request?.requestLine} , command = ${request?.command}")return super.onUploadEnd(session, request)}override fun onDownloadStart(session: FtpSession?, request: FtpRequest?): FtpletResult {log?.invoke(TAG,"onDownloadStart argument = ${request?.argument} , requestLine = ${request?.requestLine} , command = ${request?.command}")return super.onDownloadStart(session, request)}override fun onDownloadEnd(session: FtpSession?, request: FtpRequest?): FtpletResult {log?.invoke(TAG,"onDownloadEnd argument = ${request?.argument} , requestLine = ${request?.requestLine} , command = ${request?.command}")return super.onDownloadEnd(session, request)} }2 客戶端
引入庫:
//ftpimplementation 'commons-net:commons-net:3.8.0'implementation files('libs/ftpserver-core-1.0.6.jar')2.1 客戶端的代碼實現
import android.net.Uri import android.util.Log import com.demo.client.model.ClientConfig import kotlinx.coroutines.* import org.apache.commons.net.ftp.FTPClient import org.apache.commons.net.ftp.FTPReply import java.io.* import java.net.SocketExceptionclass FtpClientManager {companion object {private const val TAG = "FtpClient"private const val BUFFER_SIZE = 2 * 1024 * 1024val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {FtpClientManager()}}private val job = SupervisorJob()private val scope = CoroutineScope(Dispatchers.IO + job)var ilog: ((tag: String, content: String?) -> Unit)? = nullprivate var ftpClient: FTPClient? = nullprivate var config: ClientConfig? = nullfun connect2Server(config: ClientConfig, callback: ((result: Boolean) -> Unit)? = null) {this.config = configilog?.invoke(TAG, config.toString())val ftpUri = Uri.parse(config.ftpUrl)ftpClient = FTPClient()//設定連接超時時間ftpClient?.connectTimeout = config.connectTimeout.toInt()ftpClient?.setDataTimeout(config.connectTimeout.toInt())ilog?.invoke(TAG, "ftpUri = ${ftpUri.host} , ${ftpUri.port}")scope.launch {try {// 要連接的FTP服務器Url,PortftpClient?.connect(ftpUri.host, ftpUri.port)// 看返回的值是不是230,如果是,表示登陸成功val reply = ftpClient?.replyCodeilog?.invoke(TAG, "reply = $reply")if (!FTPReply.isPositiveCompletion(reply!!)) {// 斷開ftpClient?.disconnect()withContext(Dispatchers.Main) {callback?.invoke(false)}return@launch}// 登陸FTP服務器val login = ftpClient?.login(config.ftpUserName ?: "anonymous", config.ftpUserPwd)ilog?.invoke(TAG, "login = $login")if (!login!!) {// 斷開ftpClient?.disconnect()withContext(Dispatchers.Main) {callback?.invoke(false)}return@launch}ftpClient?.setFileType(FTPClient.BINARY_FILE_TYPE)ftpClient?.enterLocalPassiveMode()withContext(Dispatchers.Main) {callback?.invoke(true)}} catch (e: SocketException) {e.printStackTrace()withContext(Dispatchers.Main) {callback?.invoke(false)}} catch (e: IOException) {e.printStackTrace()withContext(Dispatchers.Main) {callback?.invoke(false)}}}}fun disconnectFTP(): Boolean {return try {ftpClient?.disconnect()true} catch (e: IOException) {e.printStackTrace()false}}/*** 下載文件** @param saveFilePath 要存放的文件的路徑* @param remoteFileName 遠程FTP服務器上的那個文件的名字* @param callback true為成功,false為失敗*/fun downloadFile(saveFilePath: String, remoteFileName: String, callback: ((result: Boolean) -> Unit)? = null) {if (null == ftpClient) {callback?.invoke(false)return}if (!ftpClient!!.isConnected) {connect2Server(config!!) { result ->if (result) {realDownload(saveFilePath, remoteFileName, callback)}}} else {realDownload(saveFilePath, remoteFileName, callback)}}private fun realDownload(saveFilePath: String, remoteFileName: String, callback: ((result: Boolean) -> Unit)? = null) {scope.launch {var out: BufferedOutputStream? = nulltry {val workPath = ftpClient?.printWorkingDirectory()ilog?.invoke(TAG, "realDownload workPath = $workPath")if ("/" == workPath) {//工作目錄切換,按需看自己是否需要切換ftpClient?.changeWorkingDirectory("/resources/")}ftpClient?.bufferSize = BUFFER_SIZEval files = ftpClient!!.listFiles(remoteFileName)if (null == files || files.isEmpty()) {throw FileNotFoundException("not found remoteFileName")}val fileInfo = files[0]val localFile = File(saveFilePath)out = BufferedOutputStream(FileOutputStream(localFile))val downFlag = ftpClient!!.retrieveFile(fileInfo.name, out)out.flush()withContext(Dispatchers.Main) {callback?.invoke(downFlag)}} catch (e: Exception) {e.printStackTrace()withContext(Dispatchers.Main) {callback?.invoke(false)}} finally {out?.close()// 退出登陸FTP,關閉ftpCLient的連接ftpClient?.logout()ftpClient?.disconnect()}}}/*** 上傳文件** @param uploadFilePath 要上傳文件所在SDCard的路徑* @param callback true為成功,false為失敗*/fun uploadFile(uploadFilePath: String, callback: ((result: Boolean) -> Unit)? = null) {if (null == ftpClient) {callback?.invoke(false)return}if (!ftpClient!!.isConnected) {connect2Server(config!!) { result ->if (result) {realUpload(uploadFilePath, callback)}}} else {realUpload(uploadFilePath, callback)}}private fun realUpload(uploadFilePath: String, callback: ((result: Boolean) -> Unit)? = null) {val uoloadFile = File(uploadFilePath)if (!uoloadFile.exists()) {callback?.invoke(false)return}scope.launch {val workPath = ftpClient?.printWorkingDirectory()ilog?.invoke(TAG, "realUpload workPath = $workPath")if ("/" == workPath) {//工作目錄切換,按需看自己是否需要切換ftpClient?.changeWorkingDirectory("/resources/")}// 設置上傳文件需要的一些基本信息ftpClient?.bufferSize = BUFFER_SIZEftpClient?.controlEncoding = "UTF-8"ftpClient?.enterLocalPassiveMode()var fileInputStream: FileInputStream? = nulltry {fileInputStream = FileInputStream(uploadFilePath)val uploadFlag = ftpClient!!.storeFile(uoloadFile.name, fileInputStream)withContext(Dispatchers.Main) {callback?.invoke(uploadFlag)}} catch (e: Exception) {e.printStackTrace()withContext(Dispatchers.Main) {callback?.invoke(false)}} finally {fileInputStream?.close()// 退出登陸FTP,關閉ftpCLient的連接ftpClient?.logout()ftpClient?.disconnect()}}} }附件
依賴庫下載地址:
https://mina.apache.org/downloads-mina_2_0.html
https://mina.apache.org/ftpserver-project/old-downloads.html
總結
以上是生活随笔為你收集整理的Android局域网实现FTP文件上传下载客户端与服务端的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 触摸检测芯片VKD233HH稳压电路电路
- 下一篇: 硬件EMC测试用例及测试判据