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

(二十四)ATP应用测试平台——springboot集成fastdfs上传与下载功能

前言

本节内容我们主要介绍一下如何在springboot项目中集成fastdfs组件,实现文件的上传与下载。关于fastdfs服务中间键的安装过程,本节内容不做介绍。fastdfs是一个轻量级的分布式文件系统,也是我们文件存储中常常使用的组件之一,主要包括文件存储、文件同步、文件访问,实现了文件存储和负载均衡的问题。

正文

①引入fastdfs客户端的maven依赖

<dependency><groupId>com.github.tobato</groupId><artifactId>fastdfs-client</artifactId><version>1.27.2</version>
</dependency>

 ②在application.yml配置fastdfs的属性参数值

fdfs:so-timeout: 1501 # 超时时间connect-timeout: 601 # 连接超时时间tracker-list: # tracker地址:你的虚拟机服务器地址+端口(默认是22122)- 125.27.107.218:22122

 ③引入fastdfs客户端组件,交由spring管理

package com.ht.atp.plat.config;import com.github.tobato.fastdfs.FdfsClientConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.context.annotation.Import;
import org.springframework.jmx.support.RegistrationPolicy;@Configuration
@Import(FdfsClientConfig.class)
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class FastDfsConfig {}

 ④创建springboot文件上传与下载的控制层接口FdfsRecordController.class

package com.ht.atp.plat.controller;import com.ht.atp.plat.common.Result;
import com.ht.atp.plat.service.FdfsRecordService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;@Api(tags = {"文件管理"})
@RestController
@RequestMapping("/v1/fdfs/record")
public class FdfsRecordController {@Autowiredprivate FdfsRecordService fdfsRecordService;@ApiOperation(value = "文件上传")@PostMapping(value = "uploadFile")public Result<String> uploadFile(@ApiParam(name = "file", value = "上传的文件")@RequestParam(value = "file") MultipartFile file) {String url = fdfsRecordService.uploadFile(file);return Result.success(url);}@ApiOperation(value = "文件下载")@GetMapping(value = "downloadFile")public Result<String> downloadFile(@ApiParam(name = "url", value = "下载地址")@RequestParam(value = "url") String url) {String data = fdfsRecordService.downloadFile(url);return Result.success(data);}}

 ⑤创建springboot文件上传与下载的业务接口层FdfsRecordService.class

package com.ht.atp.plat.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.ht.atp.plat.entity.FdfsRecord;
import org.springframework.web.multipart.MultipartFile;public interface FdfsRecordService extends IService<FdfsRecord> {/*** 上传文件** @param file* @return*/String uploadFile(MultipartFile file);/*** 文件下载* @param url* @return*/String downloadFile(String url);
}

  ⑥创建springboot文件上传与下载的业务接口实现层FdfsRecordServiceImpl.class

package com.ht.atp.plat.service.impl;import cn.hutool.core.codec.Base64;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.ht.atp.plat.entity.FdfsRecord;
import com.ht.atp.plat.exception.BusinessException;
import com.ht.atp.plat.mapper.FdfsRecordMapper;
import com.ht.atp.plat.service.FdfsRecordService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.time.LocalDateTime;@Service
public class FdfsRecordServiceImpl extends ServiceImpl<FdfsRecordMapper, FdfsRecord> implements FdfsRecordService {@Autowiredprivate FastFileStorageClient storageClient;@Overridepublic String uploadFile(MultipartFile file) {try {BufferedImage bufferedImage = ImageIO.read(file.getInputStream());if (bufferedImage == null) {throw new BusinessException("文件内容不合法,无法上传!");}String fileName = file.getOriginalFilename();String suffix = "";if (StringUtils.isNotEmpty(fileName)) {String[] splitFileName = fileName.split("\\.");if (splitFileName != null && splitFileName.length > 1) {suffix = splitFileName[splitFileName.length - 1];}}FdfsRecord fdfsRecord = new FdfsRecord();fdfsRecord.setModifyTime(LocalDateTime.now());fdfsRecord.setCreateTime(LocalDateTime.now());fdfsRecord.setSuffixName(suffix);fdfsRecord.setName(fileName);StorePath storePath = this.storageClient.uploadFile(file.getInputStream(), file.getSize(), suffix, null);fdfsRecord.setUrl(storePath.getFullPath());baseMapper.insert(fdfsRecord);return storePath.getFullPath();} catch (Exception e) {throw new BusinessException("文件上传服务异常,请稍后重试!");}}@Overridepublic String downloadFile(String url) {String group = url.substring(0, url.indexOf("/"));String path = url.substring(url.indexOf("/") + 1);DownloadByteArray byteArray = new DownloadByteArray();byte[] data = this.storageClient.downloadFile(group, path, byteArray);String encodeData = Base64.encode(data);return encodeData;}
}

⑦创建springboot文件资源信息存储的持久化层FdfsRecordMapper.class,实现文件资源信息的持久化存储

package com.ht.atp.plat.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ht.atp.plat.entity.FdfsRecord;public interface FdfsRecordMapper extends BaseMapper<FdfsRecord> {}

⑧创建springboot文件资源信息存储的持久化层FdfsRecordMapper.xml,实现文件资源信息的持久化存储

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ht.atp.plat.mapper.FdfsRecordMapper"></mapper>

 ⑨创建springboot文件资源信息存储的实体类FdfsRecord.class

package com.ht.atp.plat.entity;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;import java.io.Serializable;
import java.time.LocalDateTime;@Getter
@Setter
@TableName("fdfs_record")
@ApiModel(value = "FdfsRecord对象", description = "")
public class FdfsRecord implements Serializable {private static final long serialVersionUID = 1L;@ApiModelProperty("主键ID")@TableId(value = "id", type = IdType.ASSIGN_ID)private String id;@ApiModelProperty("业务ID")@TableField("business_id")private String businessId;@ApiModelProperty("服务名称")@TableField("service_name")private String serviceName;@ApiModelProperty("文件名称")@TableField("name")private String name;@ApiModelProperty("文件地址")@TableField("url")private String url;@ApiModelProperty("后缀名称")@TableField("suffix_name")private String suffixName;@ApiModelProperty("创建时间")@TableField("create_time")private LocalDateTime createTime;@ApiModelProperty("创建人")@TableField("create_user")private String createUser;@ApiModelProperty("修改时间")@TableField("modify_time")private LocalDateTime modifyTime;@ApiModelProperty("修改人")@TableField("modify_user")private String modifyUser;}

⑩ 使用swagger测试文件上传功能

 ⑪使用swagger测试文件下载功能

结语

通过至此,关于springboot集成fastdfs上传与下载功能到这里就结束了,下期见。。。

相关文章:

(二十四)ATP应用测试平台——springboot集成fastdfs上传与下载功能

前言 本节内容我们主要介绍一下如何在springboot项目中集成fastdfs组件&#xff0c;实现文件的上传与下载。关于fastdfs服务中间键的安装过程&#xff0c;本节内容不做介绍。fastdfs是一个轻量级的分布式文件系统&#xff0c;也是我们文件存储中常常使用的组件之一&#xff0c…...

linux好用命令+vs快捷键

linux好用命令 功能指令跳转到vim界面的最后一行shift键g复制当前路径下所有文件和目录&#xff08;加-r才行&#xff09;到target目录cp -r * /home/target删除指定文件rm -rf test.txt文件重命名&#xff08;-i交互式提示&#xff09;mv -i file1 file2移动某个内容&#xf…...

Git 构建分布式版本控制系统

版本控制概念Gitlab部署1.版本控制概念 1.1分类 &#xff08;一&#xff09;1 本地版本控制系统&#xff08;传统模式&#xff09; &#xff08;二&#xff09;2 集中化的版本控制系统 CVS、Subversion&#xff08;SVN&#xff09; &#xff08;三&#xff09;3 分布式…...

Day891.一主多从的切换正确性 -MySQL实战

一主多从的切换正确性 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于一主多从的切换正确性的内容。 在切换任务的时候&#xff0c;要先主动跳过这些错误&#xff0c;通过主动跳过一个事务或者直接设置跳过指定的错误&#xff0c;用GTID解决找同步位点的问题 大多…...

【论文笔记】图像修复Learning Joint Spatial-Temporal Transformations for Video Inpainting

论文地址&#xff1a;https://arxiv.org/abs/2007.10247 源码地址&#xff1a;GitHub - researchmm/STTN: [ECCV2020] STTN: Learning Joint Spatial-Temporal Transformations for Video Inpainting 一、项目介绍 当下SITA的方法大多采用注意模型&#xff0c;通过搜索参考帧…...

代码随想录算法训练营第二天 | 977.有序数组的平方 、209.长度最小的子数组 、59.螺旋矩阵II、总结

打卡第二天&#xff0c;认真做了两道题目&#xff0c;顶不住了好困&#xff0c;明天早上练完车回来再重新看看。 今日任务 第一章数组 977.有序数组的平方209.长度最小的子数组59.螺旋矩阵II 977.有序数组的平方 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每…...

Python pickle模块:实现Python对象的持久化存储

Python 中有个序列化过程叫作 pickle&#xff0c;它能够实现任意对象与文本之间的相互转化&#xff0c;也可以实现任意对象与二进制之间的相互转化。也就是说&#xff0c;pickle 可以实现 Python 对象的存储及恢复。值得一提的是&#xff0c;pickle 是 python 语言的一个标准模…...

【C++】C/C++内存管理

文章目录1. C/C内存分布2. C语言当中的动态内存管理3. C 内存管理方式3.1 new/delete操作内置类型3.2 new和delete操作自定义类型4. operator new 和operator delete 函数5. new和delete的实现原理5.1 内置类型5.2 自定义类型6. 定位new表达式(placement-new)7. 常见面试题7.1 …...

【测试】自动化测试02

努力经营当下&#xff0c;直至未来明朗&#xff01; 文章目录前言 回顾 预告一、常见的元素操作1. 输入文本sendKeys()2. 点击click3. 提交submit&#xff08;通过回车键提交&#xff09;4. 清除clear5. 获取文本getText()6. 获取属性对应的值getAttribute()7. 查看title和ur…...

Python空间分析| 02 利用Python计算空间局部自相关(LISA)

局部空间自相关 import esda import numpy as np import pandas as pd import libpysal as lps import geopandas as gpd import contextily as ctx import matplotlib.pyplot as plt from geopandas import GeoDataFrame from shapely.geometry import Point from pylab im…...

idea快捷编码:生成for循环、主函数、判空非空、生成单例方法、输出;自定义快捷表达式

前言 idea可根据输入的简单表达式进行识别&#xff0c;快速生成语句 常用的快捷编码&#xff1a;生成for循环、主函数、判空非空、生成单例方法、输出 自定义快捷表达式 博客地址&#xff1a;芒果橙的个人博客 【http://mangocheng.com】 一、idea默认的快捷表达式查看 Editor…...

【Spring】@Value注入配置文件 application.yml 中的值失败怎么办

本期目录一、 问题背景二、 问题原因三、 解决方法一、 问题背景 今天碰到的问题是用 Value 注解无法注入配置文件 application.yml 中的配置值。 检查过该类已经交给 Spring 容器管理了&#xff0c;即已经在类上加了 Configuration 和 ConfigurationProperties(prefix &quo…...

CleanMyMac清理工具软件功能优势介绍

CleanMyMac更新最新版本x4.12&#xff0c;完美适配新版系统macOS10.14&#xff0c;拥有全新的界面。CleanMyMac可以让您安全、智能地扫描和清理整个系统&#xff0c;删除大型未使用的文件&#xff0c;减少iPod库的大小&#xff0c;最精确的应用程序卸载&#xff0c;卸载不必要的…...

【面试题】对JS中的事件冒泡、事件捕获、事件委托的理解

大厂面试题分享 面试题库后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★地址&#xff1a;前端面试题库DOM事件流&#xff08;event flow &#xff09;存在三个阶段&#xff1a;事件捕获阶段、处于目标阶段、事件冒泡阶段。Dom标准事件流的触发的先…...

SAP 理解合并会计报表

随着企业集团的发展&#xff0c;集团内部会出现越来越多的公司&#xff1b;复杂的公司结构和复杂的集团内业务&#xff0c;使得集团内部管理困难重重&#xff0c;信息渠道严重失灵。除了内部管理的需要&#xff0c;企业还有义务向相关方提供详细的和及时的信息。ERP中的合并会计…...

Ubuntu 命令常用命令——定时启动程序

crontab -e 语法 crontab[ -u user ] file或 crontab[ -u user ] { -l | -r | -e }说明: crontab是用来让使用者在固定时间或固定间隔执行程序之用&#xff0c;换句话说&#xff0c;也就是类似使用者的时程表。 -U Lser 是指设定指定user的时程表&#xff0c;这个前提是你必…...

笔试题(十三):走迷宫

# 描述 # 定义一个二维数组 N*M &#xff0c;如 5 5 数组下所示&#xff1a; # int maze[5][5] { # 0, 1, 0, 0, 0, # 0, 1, 1, 1, 0, # 0, 0, 0, 0, 0, # 0, 1, 1, 1, 0, # 0, 0, 0, 1, 0,}; # 它表示一个迷宫&#xff0c;其中的1表示墙壁&#xff0c;0表示可以走的路&#…...

Gradle相关的知识学习

这里有一套博客文章写的比较通俗易懂&#xff1a;https://www.jianshu.com/p/8e1ddd19083a...

SpringMVC的工作原理

SpringMVC的工作原理流程图 SpringMVC流程 1、 用户发送请求至前端控制器DispatcherServlet。 2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。 3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找)&#xff0c;生成处理器对象及处理器拦截…...

问卷数据分析流程

文章目录一、数据合并1. 读取数据2. 数据预览二、数据清洗1. 检验ID是否重复&#xff0c;剔除ID重复项2. 剔除填写时间小于xx分钟的值3.处理 量表题 一直选一个选项的问题三、数据清洗1.1 将问卷单选题的选项code解码&#xff0c;还原成原来的选项1.2 自动获取单选题旧的选项列…...

Java: 手动实现DeepSeek R1工具调用,基于ReAct与Spring AI的实践指南

1. DeepSeek R1工具调用的现状与挑战 DeepSeek R1作为当前热门的开源大模型&#xff0c;在实际应用中经常会遇到需要调用外部工具的场景。但很多开发者在使用过程中发现&#xff0c;当前版本的DeepSeek R1并不支持原生的工具调用功能。这意味着当我们想让模型执行诸如查询天气、…...

终极免费逆向神器Ghidra:3分钟极速安装与新手入门指南

终极免费逆向神器Ghidra&#xff1a;3分钟极速安装与新手入门指南 【免费下载链接】ghidra_installer Helper scripts to set up OpenJDK 11 and scale Ghidra for 4K on Ubuntu 18.04 / 18.10 项目地址: https://gitcode.com/gh_mirrors/gh/ghidra_installer 还在为复杂…...

Yahoo Finance API 金融数据接口实战指南:从技术原理到商业价值落地

Yahoo Finance API 金融数据接口实战指南&#xff1a;从技术原理到商业价值落地 【免费下载链接】YahooFinanceApi A handy Yahoo! Finance api wrapper, based on .NET Standard 2.0 项目地址: https://gitcode.com/gh_mirrors/ya/YahooFinanceApi 一、价值定位&#x…...

2026最新Java岗位从P5-P7的成长面试进阶资源分享!

Java岗位从P5到P7的成长路径P5到P7是Java开发者从初级到高级的关键阶段&#xff0c;需要技术深度、系统设计能力和项目经验的全面提升。以下是分阶段的资源推荐和成长建议。P5&#xff08;初级工程师&#xff09;阶段核心能力要求&#xff1a;基础语法、框架使用、简单业务开发…...

3个核心突破:LangChain的大语言模型应用开发指南

3个核心突破&#xff1a;LangChain的大语言模型应用开发指南 【免费下载链接】langchain LangChain是一个由大型语言模型 (LLM) 驱动的应用程序开发框架。。源项目地址&#xff1a;https://github.com/langchain-ai/langchain 项目地址: https://gitcode.com/GitHub_Trending…...

《机器学习》实战指南:从理论到代码的完整学习路径

1. 机器学习入门&#xff1a;从零开始的认知地图 第一次接触机器学习时&#xff0c;我被各种算法名词轰炸得头晕目眩——就像走进一家陌生的超市&#xff0c;货架上摆满看不懂标签的罐头。后来才发现&#xff0c;掌握机器学习的关键在于建立正确的认知框架。这里分享我摸索出的…...

恒压供水系统:西门子224XP与昆仑TPC7062触摸屏的完美搭档

恒压供水西门子224XP昆仑tpc7062触摸屏.最多控制41泵&#xff0c;可直接用于项目工程 主要功能&#xff1a; 1、1-4台主泵十1辅泵、箱式、无负压式&#xff0c;一拖一,一拖多&#xff0c;一套程序适配多种供水模式。 2、实时报警和历史报警功能。 3、多种传感器支持&#xff0c…...

ollama-QwQ-32B中文优化:提升OpenClaw处理本地文档的准确率

ollama-QwQ-32B中文优化&#xff1a;提升OpenClaw处理本地文档的准确率 1. 为什么需要专门优化中文文档处理 去年我在用OpenClaw处理公司合同时&#xff0c;发现一个尴尬现象&#xff1a;同样的合同解析任务&#xff0c;英文版能准确提取条款和日期&#xff0c;中文版却频繁出…...

OpenClaw技能扩展指南:为nanobot添加自定义QQ机器人功能

OpenClaw技能扩展指南&#xff1a;为nanobot添加自定义QQ机器人功能 1. 为什么需要QQ机器人集成 去年夏天&#xff0c;我发现自己经常在深夜调试代码时&#xff0c;需要反复切换手机和电脑查看运行结果。这种低效的操作让我开始寻找一种更优雅的解决方案——通过聊天工具直接…...

一篇关于论文复现的思考:基于领域相似度的复杂网络节点重要度评估算法

论文复现—基于领域相似度的复杂网络节点重要度评估算法 编写程序代码matlab 复现算法仿真最近在学习复杂网络的相关算法&#xff0c;看到一篇挺有意思的论文&#xff0c;讲的是基于领域相似度的节点重要度评估方法。说实话&#xff0c;这类算法听起来有点抽象&#xff0c;但…...