FtpClient文件的下载

本文提供了一个使用Java实现的FTP客户端示例代码,演示了如何连接FTP服务器、下载文件到本地并关闭连接。该示例包括错误处理,并通过具体的方法展示了文件传输的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package wingsoft.ftp.download;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import sun.net.ftp.FtpClient;
import sun.net.ftp.FtpProtocolException;
public class Ftp {
 private FtpClient ftpClient;
 
 /*
  * 链接ftp
  * @path:ftp子目录
  */
 public void conn(String ip,int port,String user,String pwd,String path){
  try {
   ftpClient=FtpClient.create();
   ftpClient.connect(new InetSocketAddress(ip,port));
   ftpClient.login(user, pwd.toCharArray());
   System.out.println("login success!");
   if(path.length()!=0){
    ftpClient.changeDirectory(path);
   }
  } catch (FtpProtocolException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 /*
  * 关闭链接
  */
 public void closeFTP(){
  try {
   ftpClient.close();
   System.out.println("关闭ftp链接");
  } catch (IOException e) {
   System.out.println("ftp链接,关闭失败");
   e.printStackTrace();
  }
 }
 
 /*
  * 从ftp上下载文件到本地
  * @param ftpFile  读取的文件名如:1.test
  * @param localFile 下载到本地的文件
  */
 public long download(String ftpFile,String localFile) {
  InputStream is = null;
  FileOutputStream os = null;
  long result = 0;
  
  //读取文件
  try {
   is = ftpClient.getFileStream(ftpFile);
   java.io.File outfile = new java.io.File(localFile);
   os = new FileOutputStream(outfile);
  } catch (FtpProtocolException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
  //byte[]
  byte[] buffer = new byte[1024];
  int c;
  try {
   while((c = is.read(buffer)) != -1){
    result = result +c;
    os.write(buffer, 0, c);
   }
  } catch (IOException e1) {
   // TODO Auto-generated catch block
   e1.printStackTrace();
  }
  
  //关闭
  if(is !=null){
   try {
    is.close();
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
  if(os!=null){
   try {
    os.close();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
  return result;
  
 }
  
 
 public static void main(String[] args) {
  Ftp ftp = new Ftp();
  ftp.conn("127.0.0.1", 21, "admin", "123","/temp");
  ftp.download("\\temp\\del.jpg","D:\\downtest\\1.jpg");
  ftp.closeFTP();
 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
}
<think>好的,我现在需要帮用户解决使用FTPClient下载文件的问题。用户之前已经问过关于retrieveFileStream返回空值的问题,现在可能想更全面地了解如何正确下载文件。首先,我得回想一下之前的回答,确保这次的内容不重复但又能衔接上。 用户可能已经遇到了问题,现在想了解正确的步骤。我需要分步骤讲解,包括连接、设置模式、获取流、处理异常等。同时,他们可能对代码结构不太清楚,所以提供一个示例代码会很有帮助。 要注意用户可能的误区,比如忘记设置被动模式,或者没有处理完命令。另外,权限和路径问题也是常见错误,需要提到。还要考虑编码问题,特别是处理中文文件名的情况,这可能在前一个问题中没有详细说明。 用户可能希望知道整个流程,而不仅仅是代码片段,所以需要分步骤解释每个环节的重要性。比如,连接服务器、登录、设置传输模式、检查文件是否存在,然后下载。同时,异常处理和资源释放也是关键,避免连接泄漏。 另外,用户可能需要调试技巧,比如启用日志来查看FTP命令交换情况,这在排查问题时非常有用。还有,错误代码的分析,如550或425,这些在之前的回复中提到过,但这里可以再次强调,帮助用户快速定位问题。 最后,总结常见问题,确保用户操作时注意这些点。比如被动模式、关闭连接、处理中断等。确保回答结构清晰,逐步引导用户完成下载过程,并预防可能出现的错误。</think>以下是使用Apache Commons Net库中`FTPClient`下载文件的完整指南: --- ### **1. 基础操作流程** ```java FTPClient ftpClient = new FTPClient(); try { // 1. 连接服务器 ftpClient.connect("ftp.example.com", 21); // 2. 登录认证 boolean loginSuccess = ftpClient.login("username", "password"); if (!loginSuccess) throw new IOException("登录失败"); // 3. 设置传输模式 ftpClient.enterLocalPassiveMode(); // 必须设置被动模式 ftpClient.setFileType(FTP.BINARY_FILE_TYPE); // 指定文件类型(二进制/文本) // 4. 检查文件是否存在 String remoteFilePath = "/path/to/remote/file.txt"; FTPFile[] files = ftpClient.listFiles(remoteFilePath); if (files.length == 0) throw new FileNotFoundException("远程文件不存在"); // 5. 下载文件 try (InputStream inputStream = ftpClient.retrieveFileStream(remoteFilePath); FileOutputStream outputStream = new FileOutputStream("local_file.txt")) { if (inputStream == null) { throw new IOException("获取文件流失败: " + ftpClient.getReplyString()); } // 6. 流数据拷贝 byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } } // 7. 确认传输完成 if (!ftpClient.completePendingCommand()) { throw new IOException("文件传输未完成"); } } finally { // 8. 关闭连接 if (ftpClient.isConnected()) { ftpClient.logout(); ftpClient.disconnect(); } } ``` --- ### **2. 关键注意事项** #### **(1) 被动模式强制要求** - 必须调用`enterLocalPassiveMode()`,否则可能因防火墙拦截导致数据通道无法建立 - 若服务器使用IPv6,需改用`enterLocalExtendedPassiveMode()` #### **(2) 文件类型匹配** - 文本文件:`ftpClient.setFileType(FTP.ASCII_FILE_TYPE)` - 图片/压缩包:`ftpClient.setFileType(FTP.BINARY_FILE_TYPE)`(默认必须显式设置) #### **(3) 流关闭顺序** - **必须**先关闭`InputStream`,再调用`completePendingCommand()` - 未执行`completePendingCommand()`会导致后续操作失败 #### **(4) 大文件处理** - 添加进度监控: ```java long totalSize = files[0].getSize(); long transferred = 0; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); transferred += bytesRead; System.out.printf("进度: %.2f%%\n", (transferred * 100.0 / totalSize)); } ``` --- ### **3. 常见错误处理** | **错误现象** | **解决方案** | |---------------------------|----------------------------------------------------------------------------| | 文件下载不完整 | 检查是否调用`completePendingCommand()`,确保使用`try-with-resources`自动关闭流 | | 中文文件名乱码 | 设置编码:`ftpClient.setControlEncoding("UTF-8")` | | 连接超时 | 增加超时设置:`ftpClient.setDefaultTimeout(30000)`(单位:毫秒) | | 下载0字节空文件 | 检查服务器文件权限:`files[0].getSize() > 0` | --- ### **4. 高级调试技巧** #### **(1) 启用协议日志** ```java ftpClient.addProtocolCommandListener( new PrintCommandListener(new PrintWriter(System.out), true) ); ``` 输出示例: ``` > USER username < 331 Password required > PASS ****** < 230 Login successful > TYPE I < 200 Type set to I > PASV < 227 Entering Passive Mode (192,168,1,100,195,123) ``` #### **(2) 错误码分析** - `530 Not logged in`:未登录或会话超时 - `550 File unavailable`:路径错误/权限不足 - `421 Connection timed out`:服务器主动断开连接 --- ### **5. 替代方法对比** | 方法 | 适用场景 | 注意事项 | |-------------------------|----------------------------------|-----------------------------------| | `retrieveFileStream()` | 大文件下载/需要自定义流处理 | 必须手动调用`completePendingCommand()` | | `retrieveFile()` | 小文件直接保存到本地 | 自动处理完成命令,但无法监控进度 | --- 通过以上步骤和注意事项,可确保可靠地完成FTP文件下载操作。若仍遇到问题,建议结合服务器日志和协议级调试信息进行深度分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值