首页 > 其他分享 >SpringBoot 策略模式 切换上传文件模式

SpringBoot 策略模式 切换上传文件模式

时间:2023-11-20 11:56:45浏览次数:32  
标签:文件 SpringBoot 模式 file fileRelativePath 上传 public String

策略模式

策略模式是指有一定行动内容的相对稳定的策略名称。

  • 我们定义一个接口(就比如接下来要实现的文件上传接口)
  • 我们定义所需要实现的策略实现类 A、B、C、D(也就是项目中所使用的四种策略阿里云Oss上传、腾讯云Cos上传、七牛云Kodo上传、本地上传)
  • 我们通过策略上下文来调用策略接口,并选择所需要使用的策略

 

策略接口

public interface UploadStrategy {

    /**
     * 上传文件
     *
     * @param file     文件
     * @param filePath 文件上传露肩
     * @return {@link String} 文件上传的全路径
     */
    String uploadFile(MultipartFile file, final String filePath);

}

  

策略实现类内部实现

@Getter
@Setter
public abstract class AbstractUploadStrategyImpl implements UploadStrategy {

    @Override
    public String uploadFile(MultipartFile file, String filePath) {
        try {

            //region 获取文件md5值 -> 获取文件后缀名 -> 生成相对路径
            String fileMd5 = XcFileUtil.getMd5(file.getInputStream());
            String extName = XcFileUtil.getExtName(file.getOriginalFilename());
            String fileRelativePath = filePath + fileMd5 + extName;
            //endregion

            //region 初始化
            initClient();
            //endregion

            //region 检测文件是否已经存在,不存在则进行上传操作
            if (!checkFileIsExisted(fileRelativePath)) {
                executeUpload(file, fileRelativePath);
            }
            //endregion

            return getPublicNetworkAccessUrl(fileRelativePath);
        } catch (IOException e) {
            throw new XcException("文件上传失败");
        }
    }

    /**
     * 初始化客户端
     */
    public abstract void initClient();

    /**
     * 检查文件是否已经存在(文件MD5值唯一)
     *
     * @param fileRelativePath 文件相对路径
     * @return true 已经存在  false 不存在
     */
    public abstract boolean checkFileIsExisted(String fileRelativePath);

    /**
     * 执行上传操作
     *
     * @param file             文件
     * @param fileRelativePath 文件相对路径
     * @throws IOException io异常信息
     */
    public abstract void executeUpload(MultipartFile file, String fileRelativePath) throws IOException;

    /**
     * 获取公网访问路径
     *
     * @param fileRelativePath 文件相对路径
     * @return 公网访问绝对路径
     */
    public abstract String getPublicNetworkAccessUrl(String fileRelativePath);

}

  

本地上传策略具体实现
@Slf4j
@Getter
@Setter
@RequiredArgsConstructor
@Service("localUploadServiceImpl")
public class LocalUploadStrategyImpl extends AbstractUploadStrategyImpl {

    /**
     * 本地项目端口
     */
    @Value("${server.port}")
    private Integer port;

    /**
     * 前置路径 ip/域名
     */
    private String prefixUrl;

    /**
     * 构造器注入bean
     */
    private final ObjectStoreProperties properties;

    @Override
    public void initClient() {
        try {
            prefixUrl = ResourceUtils.getURL("classpath:").getPath() + "static/";
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            throw new XcException("文件不存在");
        }
        log.info("initClient Init Success...");
    }

    @Override
    public boolean checkFileIsExisted(String fileRelativePath) {
        return new File(prefixUrl + fileRelativePath).exists();
    }

    @Override
    public void executeUpload(MultipartFile file, String fileRelativePath) throws IOException {
        File dest = checkFolderIsExisted(fileRelativePath);
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
            throw new XcException("文件上传失败");
        }
    }

    @Override
    public String getPublicNetworkAccessUrl(String fileRelativePath) {
        try {
            String host = InetAddress.getLocalHost().getHostAddress();
            if (StringUtils.isEmpty(properties.getLocal().getDomainUrl())) {
                return String.format("http://%s:%d%s", host, port, fileRelativePath);
            }
            return properties.getLocal().getDomainUrl() + fileRelativePath;
        } catch (UnknownHostException e) {
            throw new XcException("HttpCodeEnum.UNKNOWN_ERROR");
        }
    }


    /**
     * 检查文件夹是否存在,若不存在则创建文件夹,最终返回上传文件
     *
     * @param fileRelativePath 文件相对路径
     * @return {@link  File} 文件
     */
    private File checkFolderIsExisted(String fileRelativePath) {
        File rootPath = new File(prefixUrl + fileRelativePath);
        if (!rootPath.exists()) {
            if (!rootPath.mkdirs()) {
                throw new XcException("文件夹创建失败");
            }
        }
        return rootPath;
    }

}

  

策略上下文实现

@Component
@RequiredArgsConstructor
public class UploadStrategyContext {

    private final Map<String, UploadStrategy> uploadStrategyMap;

    /**
     * 执行上传策略
     *
     * @param file     文件
     * @param filePath 文件上传路径前缀
     * @return {@link String} 文件上传全路径
     */
    public String executeUploadStrategy(MultipartFile file, final String filePath, String uploadServiceName) {
        // 执行特定的上传策略
        return uploadStrategyMap.get(uploadServiceName).uploadFile(file, filePath);
    }

}

  

上传测试

文章来源:https://mp.weixin.qq.com/s/Bi7tFfKHXpBkXNpbTMR2lg

案例代码: https://gitcode.net/nanshen__/store-object

 

标签:文件,SpringBoot,模式,file,fileRelativePath,上传,public,String
From: https://www.cnblogs.com/ooo0/p/17843618.html

相关文章

  • vue2+element+vue-quill-editor实现富文本框组件(使用链接引入视频+上传本地视频+上传
    参考文档:https://www.duidaima.com/Group/Topic/Vue/12272前提不赘述,npm引入插件并全局导入 components文件夹下创建ArticleEditor.vue:<template><divclass=""><!--富文本框--><quill-editorref="myQuillEditor"v-bind:va......
  • springboot 控制序列化反序列化示例(接口返回数据处理/接口接收数据处理)
    1.返回Long转JSONpackagecom.mingx.drone.config;importcom.fasterxml.jackson.core.JsonGenerator;importcom.fasterxml.jackson.databind.JsonSerializer;importcom.fasterxml.jackson.databind.SerializerProvider;importjava.io.IOException;/***@Descript......
  • 学习随笔(设计模式:外观模式)
    内容今天学习了外观模式。1.外观模式,为子系统中的一组接口提供了一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。2.起始很多现在的软件思路都是遵从于外观模式,它完美的依赖倒转原则和迪米特法则的思想。3.软件编程采用三层架构,数据访问层、业务......
  • 新建springboot项目,访问前端界面
    直接在IDEA中下载依赖会比较慢,将常用依赖下载到本地,然后从本地加载依赖会比较快。(方法可以搜,很多) pom.xml<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quo......
  • 【漏洞复现】金蝶OA-EAS系统 uploadLogo.action 任意文件上传漏洞(0day)
    阅读须知    此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失,均由使用者本人负责。本文所提供的工具仅......
  • 命令模式
    实验16:命令模式本次实验属于模仿型实验,通过本次实验学生将掌握以下内容: 1、理解命令模式的动机,掌握该模式的结构;2、能够利用命令模式解决实际问题。 [实验任务一]:多次撤销和重复的命令模式某系统需要提供一个命令集合(注:可以使用链表,栈等集合对象实现),用于存储一系列命令对......
  • 每日随笔——外观模式
    实验任务一]:计算机开启在计算机主机(Mainframe)中,只需要按下主机的开机按钮(on()),即可调用其他硬件设备和软件的启动方法,如内存(Memory)的自检(check())、CPU的运行(run())、硬盘(HardDisk)的读取(read())、操作系统(OS)的载入(load()),如果某一过程发生错误则计算机启动失败。......
  • 实验18:迭代器模式
    软件设计                 石家庄铁道大学信息学院 实验18:迭代器模式本次实验属于模仿型实验,通过本次实验学生将掌握以下内容: 1、理解迭代器模式的动机,掌握该模式的结构;2、能够利用迭代器模式解决实际问题。 [实验任务一]:JAVA和C++常见数据结构迭代器......
  • Netty源码学习4——服务端是处理新连接的&netty的reactor模式
    系列文章目录和关于我零丶引入在前面的源码学习中,梳理了服务端的启动,以及NioEventLoop事件循环的工作流程,并了解了Netty处理网络io重要的Channel,ChannelHandler,ChannelPipeline。这一篇将学习服务端是如何构建新的连接。一丶网络包接收流程当客户端发送的网络数据帧通过网......
  • 单例模式
    某酒管集团-单例模式对性能的影响及思考 摘要: 大概一年前开始在思考构造函数中依赖注入较多,这对系统性能及硬件资源消耗产生一些优化想法。一般较多公司的项目都使用Autofac 依赖注入(Scoped作用域),但是发现过多的对象产生会消耗 CPU,内存并给GC(垃圾回收)造成一定......