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) {}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/198648.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

redis配置介绍

redis配置详解 一、redis.conf二、持久化1、RDB① 触发机制② 优缺点③ 恢复rdb 2、AOF① 优缺点② 恢复aof 三、发布订阅 一、redis.conf # -----NETWORK----- # 设置绑定ip bind 127.0.0.1 -::1 # 设置redis保护&#xff0c;只能通过绑定在本地回环地址上的网络接口进行访问…

javaweb校车校园车辆管理系统springboot+jsp

结构设计&#xff1a;总体采用B/S结构设计模式 (1)用户登录模块&#xff1a;用户通过手动登录&#xff0c;检测是否是校内人员的车辆。 (2)用户车辆信息编辑、上传、模块&#xff1a;通过上传车辆入场信息的操作权限&#xff0c;以用户的名义发布资料上传至校园停车场系统中。…

在eclipse中安装python插件:PyDev

在eclipse中安装插件PyDev&#xff0c;就可以在eclipse中开发python了。 PyDev的官网&#xff1a;https://www.pydev.org/ 不过可以直接在eclipse中用Marketplace安装&#xff08;备注&#xff1a;有可能一次安装不成功&#xff0c;是因为下载太慢了&#xff0c;多试几次&…

3、RocketMQ源码分析(三)

RocketMQ源码-NameServer架构设计及启动流程 本文我们来分析NameServer相关代码&#xff0c;在正式分析源码前&#xff0c;我们先来回忆下NameServer的功能&#xff1a; NameServer是一个非常简单的Topic路由注册中心&#xff0c;其角色类似Dubbo中的zookeeper&#xff0c;支…

【AXI死锁】

单主机单从机死锁 AXI4没有WID,所以比较严格,即写数据通道的数据必须严格的按照写地址通道的数据顺序传送,比如AW通道发送ADDR0,ADDR1,ADDR2三笔写操作,每个写操作burst length=2,那么W通道的顺序在AXI4协议的规定下必须为:WDATA0_0,WDATA0_1,WDATA1_0,WDATA1_1,WDATA2_0…

Jdk1.8日期类(LocalDate、LocalTime、LocalDateTime)

Jdk1.8新增三大日期常量类&#xff0c;与String类相同都是通过final来修饰&#xff0c;线程安全。 LocalDate&#xff1a;表示日期&#xff08;年月日&#xff09; LocalTime &#xff1a;表示时间&#xff08;时分秒&#xff09; LocalDateTime&#xff1a;表示时间 日期 &…

将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。

题目描述&#xff1a;将两个有序顺序表合并为一个新的有序顺序表&#xff0c;并由函数返回结果顺序表。 SqList Merge(SqList A, SqList B) {SqList C; // 定义新的有序顺序表C&#xff0c;用于存储合并后的结果C.length 0; // 初始化C的长度为0int i 0; // 指针i用于遍历顺…

LeetCode刷题---两两交换链表中的节点

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏&#xff1a;http://t.csdnimg.cn/D9LVS 前言&#xff1a;这个专栏主要讲述递归递归、搜索与回溯算法&#xff0c;所以下面题目主要也是这些算法做的 我讲述题目会把讲解部分分为3个部分…

dubbo框架技术文档-《spring-boot整合dubbo框架搭建+配置文件》框架的本地基础搭建

阿丹&#xff1a; 目前流行的微服务更多的就是dubbo和springcould微服务。之前阿丹没有出过dubbo相关的文章&#xff0c;因为之前接触springcould的微服务概念比较多一点&#xff0c;但是相对于springcould来说&#xff0c;springcould服务之间的调用是大多是使用了nacos&#…

每日一题:LeetCode-75. 颜色分类

每日一题系列&#xff08;day 12&#xff09; 前言&#xff1a; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f50e…

黑马头条数据管理平台项目总结

今天主要看了该项目的介绍&#xff0c;这个黑马头条数据管理平台项目主要包括登录、用户的权限判断、文章内容列表的筛选和分页、文章的增删查改还有图片和富文本编辑器这几大部分组成&#xff0c;项目配套了素材代码&#xff0c;像资源文件、第三方插件、页面文件夹、工具插件…

Vue基础知识点梳理总结归纳

在Vue中,被用来响应地更新HTML属性的指令是v-model页面挂载成功之后会触发哪一个钩子函数mounted挂载之后会进行页面的渲染v-on是动作元素不属于条件渲染指令在Vue中,下列关于Vue实例对象说法不正确的是()。A.Vue实例对象是通过new Vue({})方式创建的。B.Vue实例对象只允许…

Python中PyQt5可视化界面通过拖拽来上传文件

注&#xff1a;这个窗口提供了一个快速上传文件的小tips&#xff0c;如果需要对上传的文件进行进一步处理的可以在“processFiles”函数或者编写其它函数进行扩充就可以。 1、需要安装模块 pip install PyQt5 2、运行效果 1、通过拖拽的方式上传需要的文件到窗口&#xff0c;会…

图表控件LightningChart .NET中文教程 - 如何创建WPF 2D热图?(二)

LightningChart.NET完全由GPU加速&#xff0c;并且性能经过优化&#xff0c;可用于实时显示海量数据-超过10亿个数据点。 LightningChart包括广泛的2D&#xff0c;高级3D&#xff0c;Polar&#xff0c;Smith&#xff0c;3D饼/甜甜圈&#xff0c;地理地图和GIS图表以及适用于科学…

学习数分--简单案例1

业务背景&#xff1a;某服务类app&#xff0c;近期发现日新增用户数下滑明显。 具体描述&#xff1a;假设公司产品&#xff08;一款本地服务类app&#xff09;&#xff0c;近期发现日新增用户数下滑明显。老板要求你分析&#xff1a;数据异动的原因是什么&#xff1f; #最开始…

Java 数据结构篇-二叉树的深度优先遍历(实现:递归方式、非递归方式)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 二叉树的说明 1.1 二叉树的实现 2.0 二叉树的优先遍历说明 3.0 用递归方式实现二叉树遍历 3.1 用递归方式实现遍历 - 前序遍历 3.2 用递归方式实现遍历 - 中序遍…

第五十六天|583. 两个字符串的删除操作 72. 编辑距离

583. 两个字符串的删除操作 可以求出最大子序列然后用字符串长度去减&#xff0c;也可以用删除的思路&#xff0c;如下&#xff1a; class Solution { public:int minDistance(string word1, string word2) {vector<vector<int>> dp(word1.size()1,vector<int…

逻辑回归 使用Numpy实现逻辑回归

使用Numpy实现逻辑回归 sigmoid 函数 g ( z ) 1 ( 1 e − z ) g(z)\frac{1}{(1e^{−z} )} g(z)(1e−z)1​ # sigmoid 函数 def sigmod(z):return 1/(1np.exp(-z))线性计算与梯度下降 J ( θ ) − 1 m [ ∑ i 1 m y ( i ) l o g ⁡ ( h θ ( x ( i ) ) ) ( 1 − y ( i ) …

ROS 元功能包

ROS元功能包&#xff08;Metapackage&#xff09;是一种特殊的软件包&#xff0c;它本身并不包含任何可执行代码或数据文件。在ROS 1中&#xff0c;可以通过catkin_create_pkg命令创建元功能包。 相反&#xff0c;它的主要目的是作为一组相关功能包的集合或者依赖关系列表。使…

国标GB28181视频监控EasyCVR内网环境部署无法启动怎么办?

安防视频监控系统EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等&#xff0c;能对外分发RTMP、RTSP、HTTP-FLV、…