当前位置: 首页 > 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;确保与不同制造商的设备和控制系统兼容。 数据转换和适配&…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...