使用FTP下载文件connect.retrieveFileStream(filename) 获取不到InputStream流,返回null的问题

有个业务是批量下载多个路径文件,多个的时候总有某几个ftp.retrieveFileStream返回为空,即使关闭了流也不行,解决方案如注释,使用全路径访问ftp

        path = path.replace("\\", "/");
        String fileName = path.substring(path.lastIndexOf("/") + 1);
        //不用使用文件目录切换来查找文件,直接使用全路径访问
        //ftp.changeWorkingDirectory(path.substring(0, path.lastIndexOf("/")));
        InputStream in = ftp.retrieveFileStream(path);


        //使用完毕后关闭流等操作必须手动
        in.close();
        ftp.completePendingCommand();
public void downloadFtpFile(String url, HttpServletResponse response) throws IOException { // 解析 URL,获取 FTP 服务器 IP、端口、用户名、密码、文件路径和文件名等信息 FtpInfo ftpInfo = parseFtpUrl(url); if (ftpInfo == null) { logger.error("Invalid URL: " + url); return; } FTPClient ftpClient = null; try { // 建立 FTP 连接 ftpClient = new FTPClient(); ftpClient.connect(ftpInfo.getIp(), ftpInfo.getPort()); if (StringUtils.hasText(ftpInfo.getUserName())) { ftpClient.login(ftpInfo.getUserName(), ftpInfo.getPassword()); // 用户名密码登录 } else { ftpClient.login("anonymous", ""); // 匿名登录 } if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) { throw new IOException("Failed to connect to FTP server: " + ftpInfo.getIp() + ":" + ftpInfo.getPort()); } // 切换到指定目录 ftpClient.changeWorkingDirectory(ftpInfo.getFilePath()); // 获取下载文件InputStream InputStream is = ftpClient.retrieveFileStream(new String(ftpInfo.getFilename().getBytes("GB2312"), StandardCharsets.ISO_8859_1)); if (is == null) { throw new IOException("Failed to retrieve file from FTP server: " + ftpInfo.getFilename()); } // 设置响应头,输出文件 response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "inline; filename=" + ftpInfo.getFilename()); OutputStream os = response.getOutputStream(); IOUtils.copy(is, os); os.flush(); } catch (IOException e) { logger.error("Failed to download file from FTP server: " + ftpInfo.getFilename(), e); } finally { if (ftpClient != null) { ftpClient.logout(); ftpClient.disconnect(); } } } private FtpInfo parseFtpUrl(String url) { Pattern pattern = Pattern.compile("^ftp://([^/@]+)(?::(\d+))?(/[^@]*)?/([^@/]+)$"); Matcher matcher = pattern.matcher(url); if (!matcher.matches()) { return null; } FtpInfo ftpInfo = new FtpInfo(); ftpInfo.setIp(matcher.group(1)); ftpInfo.setPort(Integer.parseInt(StringUtils.defaultIfBlank(matcher.group(2), "21"))); String[] userInfo = matcher.group().split(":"); if (userInfo.length == 2) { ftpInfo.setUserName(userInfo[0]); ftpInfo.setPassword(userInfo[1]); } ftpInfo.setFilePath(StringUtils.defaultIfBlank(matcher.group(3), "/")); ftpInfo.setFilename(matcher.group(4)); return ftpInfo; } private static class FtpInfo { private String ip; private int port = 21; private String userName; private String password; private String filePath = "/"; private String filename; // getters and setters }优化一下代码
最新发布
06-03
以下是优化后的代码: ``` public void downloadFtpFile(String url, HttpServletResponse response) throws IOException { FtpInfo ftpInfo = parseFtpUrl(url); if (ftpInfo == null) { logger.error("Invalid URL: " + url); return; } try (FTPClient ftpClient = new FTPClient()) { ftpClient.connect(ftpInfo.getIp(), ftpInfo.getPort()); if (StringUtils.hasText(ftpInfo.getUserName())) { ftpClient.login(ftpInfo.getUserName(), ftpInfo.getPassword()); } else { ftpClient.login("anonymous", ""); } if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) { throw new IOException("Failed to connect to FTP server: " + ftpInfo.getIp() + ":" + ftpInfo.getPort()); } ftpClient.changeWorkingDirectory(ftpInfo.getFilePath()); try (InputStream is = ftpClient.retrieveFileStream(new String(ftpInfo.getFilename().getBytes("GB2312"), StandardCharsets.ISO_8859_1))) { if (is == null) { throw new IOException("Failed to retrieve file from FTP server: " + ftpInfo.getFilename()); } response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "inline; filename=" + ftpInfo.getFilename()); try (OutputStream os = response.getOutputStream()) { IOUtils.copy(is, os); os.flush(); } } } catch (IOException e) { logger.error("Failed to download file from FTP server: " + ftpInfo.getFilename(), e); } } private FtpInfo parseFtpUrl(String url) { Pattern pattern = Pattern.compile("^ftp://([^/@]+)(?::(\\d+))?(/[^@]*)?/([^@/]+)$"); Matcher matcher = pattern.matcher(url); if (!matcher.matches()) { return null; } FtpInfo ftpInfo = new FtpInfo(); ftpInfo.setIp(matcher.group(1)); ftpInfo.setPort(Integer.parseInt(StringUtils.defaultIfBlank(matcher.group(2), "21"))); String[] userInfo = matcher.group().split(":"); if (userInfo.length == 2) { ftpInfo.setUserName(userInfo[0]); ftpInfo.setPassword(userInfo[1]); } ftpInfo.setFilePath(StringUtils.defaultIfBlank(matcher.group(3), "/")); ftpInfo.setFilename(matcher.group(4)); return ftpInfo; } ``` 优化后的代码主要做了以下几点改进: 1. 使用 try-with-resources 来自动管理 ftpClientInputStream 和 OutputStream 等资源的释放,避免手动关闭资源时可能出现的异常。 2. 使用正则表达式和 Matcher 类来解析 FTP URL,简化了代码逻辑。 3. 将 FtpInfo 类定义为静态内部类,避免了类名冲突和过多的类定义。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值