当前位置: 首页 > news >正文

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的目录&#xff0c;添加到系统环境变量的Path中即可&#xff0c;VSCode会自动识别及添加 2、pip 使用 pip常用命令和一些坑 查看已安装库的版本号 pip show 库名称 通过git 仓库安装第三方库 pip install git仓库地…...

【Vulnhub 靶场】【Coffee Addicts: 1】【简单-中等】【20210520】

1、环境介绍 靶场介绍&#xff1a;https://www.vulnhub.com/entry/coffee-addicts-1,699/ 靶场下载&#xff1a;https://download.vulnhub.com/coffeeaddicts/coffeeaddicts.ova 靶场难度&#xff1a;简单 - 中等 发布日期&#xff1a;2021年5月20日 文件大小&#xff1a;1.3 …...

codeforces每日两道思维题(第 二 天)

第二天 1 B. Same Parity Summands 原题链接&#xff1a;Problem - 1352B - Codeforces rating : 1200 题目描述&#xff1a; 给定两个正整数 n&#xff08;1≤n≤10^9&#xff09;和 k&#xff08;1≤k≤100&#xff09;。将数字 n 表示为 k 个相同奇偶性的正整数之和&…...

【网络安全】-常见的网站攻击方式详解

文章目录 介绍1. SQL 注入攻击攻击原理攻击目的防范措施 2. 跨站脚本攻击&#xff08;XSS&#xff09;攻击原理攻击目的防范措施 3. CSRF 攻击攻击原理攻击目的防范措施 4. 文件上传漏洞攻击原理攻击目的防范措施 5. 点击劫持攻击原理攻击目的防范措施 结论 介绍 在数字时代&a…...

ElasticSearch学习笔记(一)

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

go写文件后出现大量NUL字符问题记录

目录 背景 看看修改前 修改后 原因 背景 写文件完成后发现&#xff1a; size明显也和正常的不相等。 看看修改前 buf : make([]byte, 64) buffer : bytes.NewBuffer(buf)// ...其它逻辑使得buffer有值// 打开即将要写入的文件&#xff0c;不存在则创建 f, err : os.Open…...

【Collection - PriorityQueue源码解析】

本文主要对Collection - PriorityQueue进行源码解析。 Collection - PriorityQueue源码解析 概述方法剖析 add()和offer()element()和peek()remove()和poll()remove(Object o) 概述 前面以Java ArrayDeque为例讲解了Stack和Queue&#xff0c;其实还有一种特殊的队列叫做Priori…...

Javascript_根据截止日期超时自动返回

例如定时交卷功能&#xff0c;隐藏一个input id"endTime"存放超时时间&#xff0c;例如2023-12-01 20:56:15&#xff0c;使用如下代码即可实现超时自动处理。 <script src"/jquery.min.js"></script><script type"text/javascript&qu…...

记录 | vscode设置自动换行

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

k8s引用环境变量

一 定义环境变量 ① 如何在k8s中定义环境变量 env、configmap、secret补充&#xff1a; k8s 创建Service自带的环境变量 ② 从pod属性中获取 kubectl explain deploy.spec.template.spec.containers.env.valueFrom关注&#xff1a; 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’的解决办法。 然后是咋解决的呢&#xff0c;真是丢脸 由于我是直接从浏览器复制下来的ip&#xff0c;所以虽然我只复制了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-…...

轻食沙拉店外卖配送小程序商城效果如何

轻食沙拉店也是餐饮业中较为受欢迎的品类&#xff0c;其具备健康属性绿色食材涵盖广泛人群&#xff0c;虽然如此&#xff0c;但也缺乏一定市场教育&#xff0c;部分消费者依然对这一类目知之甚少&#xff0c;而商家想要进一步扩大生意&#xff0c;就需要不断品牌宣传、餐品销售…...

Oracle ADRCI工具使用说明

1.ADRCI介绍 ADRCI是一个命令行工具&#xff0c;是Oracle 11g中引入的故障可诊断性架构的一部分。 ADRCI可以完成以下&#xff1a; 查看自动诊断信息库&#xff08;ADR&#xff09;中的诊断数据。 查看Health Monitor报告。 将事件和问题信息打包到zip文件中以传输到Oracle Su…...

Amazon CodeWhisperer 正式可用, 并面向个人开发者免费开放

文章作者&#xff1a;深度-围观 北京——2023年4月18日&#xff0c;亚马逊云科技宣布&#xff0c;实时 AI 编程助手 Amazon CodeWhisperer 正式可用&#xff0c;同时推出的还有供所有开发人员免费使用的个人版&#xff08;CodeWhisperer Individual&#xff09;。CodeWhisperer…...

8-Hive原理与技术

单选题 题目1&#xff1a;按粒度大小的顺序&#xff0c;Hive数据被分为&#xff1a;数据库、数据表、桶和什么 选项: A 元祖 B 栏 C 分区 D 行 答案&#xff1a;C ------------------------------ 题目2&#xff1a;以下选项中&#xff0c;哪种类型间的转换是被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 …...

微信聊天窗口测试用例

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

Linux下配置邮箱客户端MUTT,整合msmtp + procmail + fetchmail

一、背景 在向 Linux kernel 社区提交patch补丁步骤总结&#xff08;已验证成功&#xff09;_kernel补丁-CSDN博客文章中提到如何向kernel社区以及其他类似如qemu、libvirt社区提交patch的详细步骤&#xff0c;但还有一点不足的是通过git send-email这种方法基本是只能发送patc…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...

es6+和css3新增的特性有哪些

一&#xff1a;ECMAScript 新特性&#xff08;ES6&#xff09; ES6 (2015) - 革命性更新 1&#xff0c;记住的方法&#xff0c;从一个方法里面用到了哪些技术 1&#xff0c;let /const块级作用域声明2&#xff0c;**默认参数**&#xff1a;函数参数可以设置默认值。3&#x…...