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

手把手教学 Springboot+ftp+下载图片

简单教学,复制即用的Ftp下载图片
引入配置包

        <dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency><dependency><groupId>commons-net</groupId><artifactId>commons-net</artifactId><version>3.9.0</version></dependency>

首先创建连接客户端,中间如果赋值进去找不到变量,则是自己需要配置的 ,比如host:则表示主机ip

public FTPClient connFtp() {FTPClient ftpClient = null;String errorMsg = null;try {ftpClient = new FTPClient();//设置连接超时时间ftpClient.setConnectTimeout(1000 * 30);// 连接FTP服务器if (port == 0) {ftpClient.connect(host);} else {ftpClient.connect(host, port);}// 登陆FTP服务器ftpClient.login(user, pwd);// 中文支持 ,避免图片或文件中文乱码ftpClient.setControlEncoding("GBK"); FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);conf.setServerLanguageCode("zh");// 设置文件类型为二进制(如果从FTP下载或上传的文件是压缩文件的时候,不进行该设置可能会导致获取的压缩文件解压失败)ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {ftpClient.disconnect();Assert.isTrue(false, ERROR_CONN + "用户名或密码错误");} else {log.info("FTP连接成功!");}} catch (Exception e) {log.info("登陆FTP失败,请检查FTP相关配置信息是否正确!" + e);Assert.isTrue(false, ERROR_CONN + e.getMessage());return null;}return ftpClient;}

// deviceId :其实这个是文件名,拼接的,只是我们这以这个id存的文件名,所以用这个
// batch 主要是判断是否需要批量

@Overridepublic List<MultipartFile> getFtpImage(String deviceId, boolean batch) {FTPClient ftpClient = connFtp();String imgUrl = null;List<MultipartFile>  fileList = new ArrayList<>();try {String path = null;String filename = null;//指定文件路径 和 路径下的文件名path = "/5/panorama/";filename = "5_"+deviceId+".jpg";//这一步很重要,主要是类似打开目录,ftpClient.changeWorkingDirectory(path);if(batch){FTPFile[] ftpFiles = ftpClient.listFiles();//获取目录下面文件列表,在下面for (int i =0;i<ftpFiles.length;i++){FTPFile ftpFile = ftpFiles[i];if (ftpFile.getName().equals(filename)) {// 此处表示直接返回到浏览器下载,需要添加参数  HttpServletResponse// response.setHeader("Content-disposition","attachment;filename="+ URLEncoder.encode(filename, "utf-8"));// 将文件保存到输出流outputStream中//ftpClient.retrieveFile(new String(ftpFile.getName().getBytes("GBK"), "ISO-8859-1"), outputStream);// ftpclient自带方法 将图片转换成 inputStream InputStream inputStream = ftpClient.retrieveFileStream(new String(ftpFile.getName().getBytes("GBK"), "ISO-8859-1"));MultipartFile multipartFile = FileUtil.getMultipartFile(inputStream, filename);fileList.add(multipartFile);inputStream.close();System.out.println("ftp获取图片成功。。。。");}}}else {InputStream inputStream = ftpClient.retrieveFileStream(new String(filename.getBytes("GBK"), "ISO-8859-1"));MultipartFile multipartFile = FileUtil.getMultipartFile(inputStream, filename);//如果想直接上传的话 到这里就可以调用上传方法了fileList.add(multipartFile);inputStream.close();System.out.println("ftp获取图片成功。。。。");}ftpClient.logout();} catch (UnsupportedEncodingException ex) {throw new RuntimeException(ex);} catch (IOException ex) {throw new RuntimeException(ex);}finally {if (ftpClient.isConnected()) {try {ftpClient.disconnect();} catch (IOException ioe) {}}}return fileList;}

获取指定目录下的文件列表

 public List<String> getFileNameList(String ftpDirPath) {FTPClient ftpClient = connFtp();List<String> list = new ArrayList();try {// 通过提供的文件路径获取FTPFile对象列表FTPFile[] files = ftpClient.listFiles(ftpDirPath);for (int i = 0; i < files.length; i++) {FTPFile ftpFile = files[i];if (ftpFile.isFile()) {list.add(ftpFile.getName());}}ftpClient.logout();} catch (IOException e) {log.error("错误" + e);}finally {if (ftpClient.isConnected()) {try {ftpClient.disconnect();} catch (IOException ioe) {}}}return list;}

以下这个方法主要是判断,目录下是否有这个文件,用于某个文件主要判断是否需要录取文件流

/*** 判断ftp服务器文件是否存在** @param ftpClient* @param path* @return* @throws IOException*/private static boolean existFile(FTPClient ftpClient, String path) throws IOException {boolean flag = false;FTPFile[] ftpFileArr = ftpClient.listFiles(path);if (ftpFileArr.length > 0) {flag = true;}return flag;}

后续即是扩展内容,将文件流转换成MultipartFile ,剩下的就是正常上传业务逻辑了

 import org.apache.commons.fileupload.FileItem;import org.apache.commons.fileupload.FileItemFactory;import org.apache.commons.fileupload.disk.DiskFileItem;import org.apache.commons.fileupload.disk.DiskFileItemFactory;/*** 获取封装得MultipartFile** @param inputStream inputStream* @param fileName    fileName* @return MultipartFile*/public static MultipartFile getMultipartFile(InputStream inputStream, String fileName) {FileItem fileItem = createFileItem(inputStream, fileName);//CommonsMultipartFile是feign对multipartFile的封装,但是要FileItem类对象return new CommonsMultipartFile(fileItem);}/*** FileItem类对象创建** @param inputStream inputStream* @param fileName    fileName* @return FileItem*/public static FileItem createFileItem(InputStream inputStream, String fileName) {FileItemFactory factory = new DiskFileItemFactory(16, null);String textFieldName = "file";FileItem item = factory.createItem(textFieldName, MediaType.MULTIPART_FORM_DATA_VALUE, true, fileName);int bytesRead = 0;byte[] buffer = new byte[8192];OutputStream os = null;//使用输出流输出输入流的字节try {os = item.getOutputStream();while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {os.write(buffer, 0, bytesRead);}inputStream.close();} catch (IOException e) {log.error("Stream copy exception", e);throw new IllegalArgumentException("文件上传失败");} finally {if (os != null) {try {os.close();} catch (IOException e) {log.error("Stream close exception", e);}}if (inputStream != null) {try {inputStream.close();} catch (IOException e) {log.error("Stream close exception", e);}}}return item;}

总结起来,开发中主要遇到的问题:
1,文件命名不规范,导致拉取失败
2,文件中文乱码,导致找不到
有不懂的或理解不到的,可以留言,相互探讨

相关文章:

手把手教学 Springboot+ftp+下载图片

简单教学&#xff0c;复制即用的Ftp下载图片 引入配置包 <dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency><dependency><grou…...

LaaS LLM as a service

LaaS LLM as a service 核心构成GPT 产业链如何进行商业化LLM(Large Language Model) 发展和趋势LLM(Large Language Model) 对于行业公司的分层LLM(Large Language Model) 的机遇和挑战 LaaS LLM as a service 核心构成 计算&#xff1a;算力模型&#xff1a;算法输入&…...

数据结构与算法(一)数组的相关概念和底层java实现

一、前言 从今天开始&#xff0c;笔者也开始从0学习数据结构和算法&#xff0c;但是因为这次学习比较捉急&#xff0c;所以记录的内容并不会过于详细&#xff0c;会从基础和底层代码实现以及力扣相关题目去写相关的文章&#xff0c;对于详细的概念并不会过多讲解 二、数组基础…...

歌曲推荐《最佳损友》

最佳损友 陈奕迅演唱歌曲 《最佳损友》是陈奕迅演唱的一首粤语歌曲&#xff0c;由黄伟文作词&#xff0c;Eric Kwok&#xff08;郭伟亮&#xff09;作曲。收录于专辑《Life Continues》中&#xff0c;发行于2006年6月15日。 2006年12月26日&#xff0c;该曲获得2006香港新城…...

多元共进|科技促进艺术发展,助力文化传承

科技发展助力文化和艺术的传播 融合传统与创新&#xff0c;碰撞独特魅力 一起来了解 2023 Google 开发者大会上 谷歌如何依托科技创新 推动艺术与文化连接 传承和弘扬传统文化 自 2011 年成立以来&#xff0c;谷歌艺术与文化致力于提供体验艺术和文化的新方式&#xff0c;从生成…...

Java集合(Collection、Iterator、Map、Collections)概述——Java第十三讲

前言 本讲我们将继续来讲解Java的其他重要知识点——Java集合。Java集合框架是Java编程语言中一个重要的部分,它提供了一套预定义的类和接口,供程序员使用数据结构来存储和操作一组对象。Java集合框架主要包括两种类型:一种是集合(Collection),存储一个元素列表,…...

topscoding主题库模板题

目录 模板题 【模板题】分因数&#xff08;P1101&#xff09; 【模板题】区间素数 III&#xff08;P1113&#xff09; 进制转换 III (任意转任意) &#xff08;P2463&#xff09; AB Problem&#xff08;高精度加法&#xff09; A-B Problem&#xff08;高精度减法&…...

Linux--进程间通讯--FIFO(open打开)

1. 什么是FIFO FIFO命名管道&#xff0c;也叫有名管道&#xff0c;来区分管道pipe。管道pipe只能用于有血缘关系的进程间通信&#xff0c;但通过FIFO可以实现不相关的进程之间交换数据。FIFO是Linux基础文件类型中的一种&#xff0c;但是FIFO文件在磁盘上没有数据块&#xff0c…...

哪里可以了解轻量的工作流引擎?

如果想要实现高效率的办公&#xff0c;可以使用轻量的工作流引擎低代码技术平台。随着工作量日益繁重起来&#xff0c;传统的办公制作方式已经无法满足现实需要的&#xff0c;采用轻量级的表格制作工具&#xff0c;就能在无形中缓解办公压力&#xff0c;创造更高效、灵活、优质…...

lvs负载均衡、LVS集群部署

四&#xff1a;LVS集群部署 lvs给nginx做负载均衡项目 218lvs&#xff08;DR 负载均衡器&#xff09; yum -y install ipvsadm&#xff08;安装这个工具来管理lvs&#xff09; 设置VIP192.168.142.120 创建ipvsadm的文件用来存放lvs的规则 定义策略 ipvsadm -C //清空现有…...

如何应对核心员工提离职?

最近一年互联网行情不好&#xff0c;很多大厂都在裁员&#xff0c;但裁员并不是不要人做事了。原来你这个岗位10个人做&#xff0c;企业有钱赚养得起&#xff0c;现在企业不怎么赚钱了&#xff0c;只能养4个人了。那么会有六个被裁掉。这时候对企业价值最大的4个人会被留下。也…...

建站系列(八)--- 本地开发环境搭建(WNMP)

目录 相关系列文章前言一、准备工作二、Nginx安装三、MySQL安装四、PHP安装及Nginx配置五、总结 相关系列文章 建站系列&#xff08;一&#xff09;— 网站基本常识 建站系列&#xff08;二&#xff09;— 域名、IP地址、URL、端口详解 建站系列&#xff08;三&#xff09;— …...

21天学会C++:Day8----范围for与nullptr

目录 ​编辑 1. 范围for 2. nullptr 1. 范围for 我们在写C语言循环遍历代码的时候&#xff0c;无论是用 for循环&#xff0c;while循环都需要考虑循环的起始条件&#xff0c;循环变量的递增逻辑&#xff0c;循环的结束条件。麻烦不说还可能会出错。 int main() {int arr[]…...

Linux——环境变量

✅<1>主页&#xff1a;&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;Linux——环境变量 ☂️<3>开发环境&#xff1a;Centos7 &#x1f4ac;<4>前言&#xff1a;环境变量(environment variables)一般是指在操作系统中用来指定操作…...

Screen的详细全面安装教程及Screen的用法

Screen可以大大提高终端使用效率&#xff0c;是Linux系统管理和运维的必备技能。当我们开启Screen后&#xff0c;只要Screen进程没有终止&#xff0c;其内部运行的会话都可以恢复。即使网络连接中断&#xff0c;用户也可以重新进入已开启的Screen中&#xff0c;对中断的会话进行…...

生成树、Prufer序列的计数问题:0912T1

看到生成树计数&#xff0c;很容易想到生成树计数 然后发现每个点有度数限制&#xff0c;我们可以先考虑枚举每个点的度数&#xff08;也可以是Prufer 序列中的出现次数&#xff09; 假设出现次数为 a a a&#xff0c;可以得出其生成树方案为 n ! ∏ ( a i − 1 ) ! \frac{…...

SQL_牛客网_SQL264_求每个登陆日期的次日留存率

牛客每个人最近的登录日期(五) 牛客每天有很多人登录&#xff0c;请你统计一下牛客每个日期新用户的次日留存率。 有一个登录(login)记录表&#xff0c;简况如下: id user_id client_id date 1 2 1 2020-10-12 2 3 2 2020-10-12 3 1 2 2020-10-…...

Hive 基础知识

目录 1.基础概念1.1 定义1.2 组件1.3 元数据1.4 内部表和外部表 2. Hive与关系型数据库的对比3. Hive 数据存储4. 参考文献 1.基础概念 1.1 定义 Hive是一个基于Hadoop的数据仓库基础设施工具&#xff0c;它可以将结构化的数据文件映射为一张数据库表&#xff0c;并提供类SQL查…...

【数据结构】树的基础知识及三种存储结构

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …...

ABB 3BHB003688R0101接口模块

通信接口&#xff1a;接口模块通常具有多种通信接口&#xff0c;如以太网、串行通信、Modbus、Profibus等&#xff0c;以便与其他设备和系统进行数据交换。 协议支持&#xff1a;它们支持各种通信协议&#xff0c;确保与不同制造商的设备和控制系统兼容。 数据转换和适配&…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...