java FTP客户端获取文件流假死问题
依赖 hutool
FTP配置
inspection.data.ftp.host=172.26.1.41
inspection.data.ftp.port=21
inspection.data.ftp.user=6c
inspection.data.ftp.password=6cqq123
inspection.data.ftp.charsetName=GBK
FTP配置类
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@Data
@ConfigurationProperties(prefix = "inspection.data.ftp")
public class FtpParamProperties {// ftp ipprivate String host;// ftp 端口private int port;// ftp 用户private String user;// ftp 密码private String password;// ftp 编码private String charsetName;
}
FTP工具类
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.lang.Filter;
import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.ftp.Ftp;
import cn.hutool.http.ContentType;
import com.cdtye.itps.cms.config.FtpParamProperties;
import com.cdtye.itps.cms.model.dto.DownloadDto;
import com.cdtye.itps.cms.model.dto.FtpPathTree;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Objects;@Component
public class FtpUtil {static FtpParamProperties ftpParamProperties;public static Ftp getConnect() {return new Ftp(ftpParamProperties.getHost(), ftpParamProperties.getPort(), ftpParamProperties.getUser(), ftpParamProperties.getPassword(), Charset.forName(ftpParamProperties.getCharsetName()));}public static void downLoad(DownloadDto downloadDto, HttpServletResponse response) {if (Objects.isNull(downloadDto)) {throw new RuntimeException("下载参数不能为空");}if (StringUtils.isBlank(downloadDto.getFileName())) {throw new RuntimeException("下载参数中文件名不能为空");}if (StringUtils.isBlank(downloadDto.getUrl())) {throw new RuntimeException("下载参数中url不能为空");}response.reset();response.setContentType(ContentType.OCTET_STREAM.getValue());response.setCharacterEncoding("utf-8");response.setHeader("Content-Disposition", "attachment;filename=" + downloadDto.getFileName());if (StringUtils.isNotBlank(downloadDto.getUrl())) {downFormUrl(downloadDto, response);}}private static void downFormUrl(DownloadDto downloadDto, HttpServletResponse response) {try (InputStream stream = URLUtil.getStream(URLUtil.toUrlForHttp(URLUtil.encodeFragment(downloadDto.getUrl())))) {byte[] buff = new byte[1024];OutputStream os = response.getOutputStream();int i = 0;while ((i = stream.read(buff)) != -1) {os.write(buff, 0, i);os.flush();}} catch (IOException e) {throw new RuntimeException("下载文件异常", e);}}public static FtpPathTree recursionLs(String rootPath, Filter<FTPFile> filter) throws Exception {if (StringUtils.isBlank(rootPath)) {throw new RuntimeException("目录路径不能为空");}FtpPathTree ftpPathTree = new FtpPathTree();try (Ftp ftp = FtpUtil.getConnect()) {if (!ftp.exist(rootPath)) {throw new RuntimeException("目录不存在");}ftpPathTree.setFileName(rootPath);ftpPathTree.setFileFullPath(rootPath);List<FTPFile> ftpFiles = ftp.lsFiles(rootPath, filter);if (CollectionUtils.isNotEmpty(ftpFiles)) {recursionChild(ftpFiles, ftp, ftpPathTree, filter);}} catch (Exception e) {throw e;}return ftpPathTree;}private static FtpPathTree recursionChild(List<FTPFile> ftpFiles, Ftp ftp, FtpPathTree ftpPathTree, Filter<FTPFile> filter) {if (CollectionUtils.isNotEmpty(ftpFiles)) {for (FTPFile ftpFile : ftpFiles) {String currentPath = ftpPathTree.getFileFullPath() + "/" + ftpFile.getName();if (ftpFile.isDirectory()) {
// Filter<FTPFile> filterDirectory = (f) -> Objects.nonNull(f);List<FTPFile> ftpFiles1 = ftp.lsFiles(currentPath, filter);if (CollectionUtils.isNotEmpty(ftpFiles1)) {FtpPathTree ftpPathTree2 = new FtpPathTree();ftpPathTree2.setFileName(ftpFile.getName());ftpPathTree2.setFileFullPath(currentPath);ftpPathTree.getChilds().add(recursionChild(ftpFiles1, ftp, ftpPathTree2, filter));} else {FtpPathTree ftpPathTree1 = new FtpPathTree();ftpPathTree1.setFileName(ftpFile.getName());ftpPathTree1.setFileFullPath(currentPath);ftpPathTree.getChilds().add(ftpPathTree1);}} else {FtpPathTree ftpPathTree1 = new FtpPathTree();ftpPathTree1.setFileName(ftpFile.getName());ftpPathTree1.setFileFullPath(currentPath);ftpPathTree1.setFileFlag(Boolean.TRUE);ftpPathTree.getChilds().add(ftpPathTree1);}}}return ftpPathTree;}public static void recursionFile(List<FtpPathTree> ftpPathTrees, FtpPathTree ftpPathTree) {if (Objects.nonNull(ftpPathTree)) {if (ftpPathTree.getFileFlag()) {ftpPathTrees.add(ftpPathTree);} else {if (CollectionUtils.isNotEmpty(ftpPathTree.getChilds())) {for (FtpPathTree child : ftpPathTree.getChilds()) {recursionFile(ftpPathTrees, child);}}}}}public static void downloadFile(String fileFullPath, HttpServletResponse response) throws Exception {if (StringUtils.isBlank(fileFullPath)) {throw new RuntimeException("文件路径不能为空!");}try (ServletOutputStream outputStream = response.getOutputStream(); Ftp ftp = FtpUtil.getConnect()) {if (!ftp.exist(fileFullPath)) {throw new RuntimeException("文件不存在!");}if (ftp.isDir(fileFullPath)) {throw new RuntimeException("只能下载文件!");}response.reset();String fullFileName = FileNameUtil.getName(fileFullPath);String filePath = StringUtils.substringBefore(fileFullPath, fullFileName);response.setCharacterEncoding("UTF-8");response.setContentType("application/octet-stream");response.setHeader("Content-Disposition", "attachment;filename*=utf-8'zh_cn'"+ URLEncoder.encode(fullFileName, "UTF-8").replace("+", "%20"));ftp.download(filePath, fullFileName, outputStream);outputStream.flush();}}@Autowiredpublic void setFtpParamProperties(FtpParamProperties ftpParamProperties) {FtpUtil.ftpParamProperties = ftpParamProperties;}
}
测试类
import cn.hutool.extra.ftp.Ftp;
import com.cdtye.itps.cms.util.FtpUtil;
import org.apache.commons.net.ftp.FTPClient;import java.io.InputStream;
import java.util.Objects;public class FTPTest {public static void main(String[] args) {try (Ftp ftp = FtpUtil.getConnect()) {FTPClient client = ftp.getClient();InputStream inputStream = null;try {// 开始主动模式client.enterLocalPassiveMode();inputStream = client.retrieveFileStream("FTP路径");if (Objects.nonNull(inputStream)) {// 拿到流做事情}} catch (Exception e) {} finally {if (Objects.nonNull(inputStream)) {inputStream.close();}//重点是这两行,解决假死问题client.sendNoOp();client.completePendingCommand();}} catch (Exception e) {}}
}
相关文章:
java FTP客户端获取文件流假死问题
依赖 hutool FTP配置 inspection.data.ftp.host172.26.1.41 inspection.data.ftp.port21 inspection.data.ftp.user6c inspection.data.ftp.password6cqq123 inspection.data.ftp.charsetNameGBK FTP配置类 import lombok.Data; import org.springframework.boot.context.pr…...

python使用记录
1、VSCode添加多个python解释器 只需要将对应的python.exe的目录,添加到系统环境变量的Path中即可,VSCode会自动识别及添加 2、pip 使用 pip常用命令和一些坑 查看已安装库的版本号 pip show 库名称 通过git 仓库安装第三方库 pip install git仓库地…...

【Vulnhub 靶场】【Coffee Addicts: 1】【简单-中等】【20210520】
1、环境介绍 靶场介绍:https://www.vulnhub.com/entry/coffee-addicts-1,699/ 靶场下载:https://download.vulnhub.com/coffeeaddicts/coffeeaddicts.ova 靶场难度:简单 - 中等 发布日期:2021年5月20日 文件大小:1.3 …...
codeforces每日两道思维题(第 二 天)
第二天 1 B. Same Parity Summands 原题链接:Problem - 1352B - Codeforces rating : 1200 题目描述: 给定两个正整数 n(1≤n≤10^9)和 k(1≤k≤100)。将数字 n 表示为 k 个相同奇偶性的正整数之和&…...

【网络安全】-常见的网站攻击方式详解
文章目录 介绍1. SQL 注入攻击攻击原理攻击目的防范措施 2. 跨站脚本攻击(XSS)攻击原理攻击目的防范措施 3. CSRF 攻击攻击原理攻击目的防范措施 4. 文件上传漏洞攻击原理攻击目的防范措施 5. 点击劫持攻击原理攻击目的防范措施 结论 介绍 在数字时代&a…...

ElasticSearch学习笔记(一)
计算机软件的学习,最重要的是举一反三,只要大胆尝试,认真验证自己的想法就能收到事办功倍的效果。在开始之前可以看看别人的教程做个快速的入门,然后去官方网站看看官方的教程,有中文教程固然是好,没有中文…...

go写文件后出现大量NUL字符问题记录
目录 背景 看看修改前 修改后 原因 背景 写文件完成后发现: size明显也和正常的不相等。 看看修改前 buf : make([]byte, 64) buffer : bytes.NewBuffer(buf)// ...其它逻辑使得buffer有值// 打开即将要写入的文件,不存在则创建 f, err : os.Open…...
【Collection - PriorityQueue源码解析】
本文主要对Collection - PriorityQueue进行源码解析。 Collection - PriorityQueue源码解析 概述方法剖析 add()和offer()element()和peek()remove()和poll()remove(Object o) 概述 前面以Java ArrayDeque为例讲解了Stack和Queue,其实还有一种特殊的队列叫做Priori…...
Javascript_根据截止日期超时自动返回
例如定时交卷功能,隐藏一个input id"endTime"存放超时时间,例如2023-12-01 20:56:15,使用如下代码即可实现超时自动处理。 <script src"/jquery.min.js"></script><script type"text/javascript&qu…...

记录 | vscode设置自动换行
右上菜单栏 -> 查看 -> 打开自动换行 或者还有种方式,如下, 左下角小齿轮,点击设置 然后输入 Editor: Word Wrap ,把开关打开为 on...

k8s引用环境变量
一 定义环境变量 ① 如何在k8s中定义环境变量 env、configmap、secret补充: k8s 创建Service自带的环境变量 ② 从pod属性中获取 kubectl explain deploy.spec.template.spec.containers.env.valueFrom关注: configMapKeyRef、fieldRef 和 resour…...

navicate16 2059 plugin http could not be loaded
plugin http could not be loaded 乱码 library path http.dll 今天新装一台机子的navicate遇到这个问题。 查了半天都是说 caching_sha2_password’的解决办法。 然后是咋解决的呢,真是丢脸 由于我是直接从浏览器复制下来的ip,所以虽然我只复制了ip地…...
dp-基础版动态规划(动态规划每日一题计划)10/50
最小路径和 class Solution {public static int minPathSum(int[][] grid) {int dp[][]new int[grid.length][grid[0].length];dp[0][0]grid[0][0];for(int i1;i<grid[0].length;i){dp[0][i]grid[0][i]dp[0][i-1];}for(int i1;i<grid.length;i){dp[i][0]grid[i][0]dp[i-…...

轻食沙拉店外卖配送小程序商城效果如何
轻食沙拉店也是餐饮业中较为受欢迎的品类,其具备健康属性绿色食材涵盖广泛人群,虽然如此,但也缺乏一定市场教育,部分消费者依然对这一类目知之甚少,而商家想要进一步扩大生意,就需要不断品牌宣传、餐品销售…...
Oracle ADRCI工具使用说明
1.ADRCI介绍 ADRCI是一个命令行工具,是Oracle 11g中引入的故障可诊断性架构的一部分。 ADRCI可以完成以下: 查看自动诊断信息库(ADR)中的诊断数据。 查看Health Monitor报告。 将事件和问题信息打包到zip文件中以传输到Oracle Su…...

Amazon CodeWhisperer 正式可用, 并面向个人开发者免费开放
文章作者:深度-围观 北京——2023年4月18日,亚马逊云科技宣布,实时 AI 编程助手 Amazon CodeWhisperer 正式可用,同时推出的还有供所有开发人员免费使用的个人版(CodeWhisperer Individual)。CodeWhisperer…...
8-Hive原理与技术
单选题 题目1:按粒度大小的顺序,Hive数据被分为:数据库、数据表、桶和什么 选项: A 元祖 B 栏 C 分区 D 行 答案:C ------------------------------ 题目2:以下选项中,哪种类型间的转换是被Hive查询语言…...
cloudflare Tunnel完整
下载和安装 curl -L ‘https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64’ -o ./cloudflared-linux-amd64 280 chmod x ./cloudflared-linux-amd64 281 ./cloudflared-linux-amd64 282 mv cloudflared-linux-amd64 cloudflared …...

微信聊天窗口测试用例
以前没测过客户端的测试,昨天面试被问到聊天窗口测试场景设计,感觉自己答的不好,结束后上网查了一下客户端/app测试的要点,按照测试策略来分,主要涉及到如下测试类型: 1、功能测试 2、性能测试 3、界面测试…...

Linux下配置邮箱客户端MUTT,整合msmtp + procmail + fetchmail
一、背景 在向 Linux kernel 社区提交patch补丁步骤总结(已验证成功)_kernel补丁-CSDN博客文章中提到如何向kernel社区以及其他类似如qemu、libvirt社区提交patch的详细步骤,但还有一点不足的是通过git send-email这种方法基本是只能发送patc…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...
面试高频问题
文章目录 🚀 消息队列核心技术揭秘:从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"?性能背后的秘密1.1 顺序写入与零拷贝:性能的双引擎1.2 分区并行:数据的"八车道高速公路"1.3 页缓存与批量处理…...