Android使用commons-net-3.6-ftp下载FTP文件缺失约2KB致损坏
FTP文件下载缺失数据问题修复方案
核心问题点
- 循环内提前断开连接:遍历文件时每处理一个文件就调用
disconnect(),导致FTP传输未完成收尾流程,同时后续文件无法正常建立传输连接。 - 未完成FTP传输确认:使用
retrieveFileStream获取输入流后,未调用completePendingCommand(),服务器端剩余的缓冲数据无法完全传输到本地,导致文件末尾缺失。 - 流资源管理不规范:未正确关闭输入流,也未利用自动资源管理机制确保流数据完全刷新。
修复后的下载代码
fun download(url: MapFragment) { try { ftpClient?.changeWorkingDirectory("mapa/${url.shortName}") ?: return listener?.mapDownloadStarted() val pathh = context?.getExternalFilesDir(null) ?: return val files = ftpClient?.listFiles() ?: return files.forEach { ftpFile -> val destFile = File(pathh, "ptv/maps/${ftpFile.name}") // 确保目标目录存在,避免文件创建失败 destFile.parentFile?.mkdirs() // 使用use自动管理流资源,无需手动关闭 BufferedOutputStream(FileOutputStream(destFile)).use { desFileStream -> ftpClient?.retrieveFileStream(ftpFile.name)?.use { input -> org.apache.commons.net.io.Util.copyStream(input, desFileStream) desFileStream.flush() } // 必须调用此方法确认FTP服务器的传输完成信号 ftpClient?.completePendingCommand() } } // 所有文件下载完成后统一断开连接 ftpClient?.disconnect() } catch (e: Exception) { logE(e.toString()) } }
额外注意事项
- 确认FTP配置中已正确设置二进制传输模式:
mFtpClient.setFileType(FTP.BINARY_FILE_TYPE),避免文本模式下的换行符转换导致文件结构损坏。 - 被动模式
enterLocalPassiveMode()配置正确,可避免防火墙或网络环境限制导致的传输中断。 - 若使用
retrieveFile方法简化实现,需确保参数传递正确,示例如下:
// 使用retrieveFile的简化写法 ftpClient?.retrieveFile(ftpFile.name, FileOutputStream(destFile))
内容的提问来源于stack exchange,提问作者lezn
相关产品推荐
相关产品推荐

