当前位置: 首页 > 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…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

android RelativeLayout布局

<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...