Springboot策略模式实现文件上传功能(Windows/Linux本地,oss,cos)

news2024/10/2 8:21:29

1:首先配置pom依赖:

        <!-- 阿里云oss-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.8.0</version>
        </dependency>
        <!-- 腾讯云cos-->
        <dependency>
            <groupId>com.qcloud</groupId>
            <artifactId>cos_api</artifactId>
            <version>5.6.75</version>
        </dependency>

2:application.yml:

# 上传模式 (本地 阿里云 腾讯云)
# 上传模式 (Window服务器,Linux服务器本地 阿里云 腾讯云)
upload:
  mode: windowsLocal
  linuxLocal:
    # nginx映射本地文件路径,无域名则为 ip:83
    url: https://上传子域名/
    # 本地文件存储路径
    path: /usr/local/blog/upload/
    # Windows环境下测试 这里路径对应config中mvc拦截器里面的路径
  windowsLocal:
    url: http://localhost:8080/upload/
    path: G:/桌面/博客/mongo-blog-master/springboot/src/main/resources/upload/
  oss:
    url: http://Bucket域名/
    endpoint: OSS配置endpoint
    accessKeyId: OSS配置accessKeyId
    accessKeySecret: OSS配置accessKeySecret
    bucketName: OSS配置bucketName
  cos:
    url: https://ftz-1307097786.cos.ap-beijing.myqcloud.com/
    region: ap-beijing
    secretId: AKIDhKqBJPN8mDWcWFm6oVBj4A2h7IF2lFUX
    secretKey: tBLekcFi27yb3IJ6i7GCzYt2ymLgtwmt
    bucketName: ftz-1307097786

2.1:腾讯云信息查看:secretId+secretKey在访问密钥里面查看

在这里插入图片描述

2.2:url+region+bucketName在配置管理查看

在这里插入图片描述

3:Windows本地,Linux本地,阿里云,腾讯云的配置:

3.1 :Windows本地配置:

(1):首先配置application.yml:

在这里插入图片描述

(2***):重点:配置登录拦截器,设置虚拟路径,因为浏览器不可以直接访问电脑资源目录文件,所以需要设置虚拟路径!否则会报错:Not allowed to load local resource;这里的路径要跟application.yml中的路径相匹配

 @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/upload/**").addResourceLocations("file:G:/桌面/博客/mongo-blog-master/springboot/src/main/resources/upload/");
    }

在这里插入图片描述

(3):策略枚举层:

在这里插入图片描述

package com.jjhroy.blog.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 上传模式枚举
 *
 * @author yezhiqiu
 * @date 2021/07/28
 */
@Getter
@AllArgsConstructor
public enum UploadModeEnum {
    /**
     * oss
     */
    OSS("oss", "ossUploadStrategyImpl"),
    /**
     * Linux本地
     */
    LOCAL("linuxLocal", "localUploadStrategyImpl"),

    /**
     * Windows本地
     */
    WINDOWS("windowsLocal","windowsUploadStrategyImpl"),

    /**
     * cos
     */
    COS("cos", "cosUploadStrategyImpl");

    /**
     * 模式
     */
    private final String mode;

    /**
     * 策略
     */
    private final String strategy;

    /**
     * 获取策略
     *
     * @param mode 模式
     * @return {@link String} 搜索策略
     */
    public static String getStrategy(String mode) {
        for (UploadModeEnum value : UploadModeEnum.values()) {
            if (value.getMode().equals(mode)) {
                return value.getStrategy();
            }
        }
        return null;
    }

}

(4):文件上传策略:

在这里插入图片描述

package com.jjhroy.blog.strategy.context;

import com.jjhroy.blog.enums.UploadModeEnum;
import com.jjhroy.blog.strategy.UploadStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.Map;


/**
 * 上传策略上下文
 *
 * @author yezhiqiu
 * @date 2021/07/28
 */
@Service
public class UploadStrategyContext {
    /**
     * 上传模式
     */
    @Value("${upload.mode}")
    private String uploadMode;

    @Autowired
    private Map<String, UploadStrategy> uploadStrategyMap;

    /**
     * 执行上传策略
     *
     * @param file 文件
     * @param path 路径
     * @return {@link String} 文件地址
     */
    public String executeUploadStrategy(MultipartFile file, String path) {
        return uploadStrategyMap.get(UploadModeEnum.getStrategy(uploadMode)).uploadFile(file, path);
    }


    /**
     * 执行上传策略
     *
     * @param fileName    文件名称
     * @param inputStream 输入流
     * @param path        路径
     * @return {@link String} 文件地址
     */
    public String executeUploadStrategy(String fileName, InputStream inputStream, String path) {
        return uploadStrategyMap.get(UploadModeEnum.getStrategy(uploadMode)).uploadFile(fileName, inputStream, path);
    }

}

(5):本地路径上传策略方法实现层:WindowsUploadStrategyImpl:

在这里插入图片描述

package com.jjhroy.blog.strategy.impl;

import com.jjhroy.blog.enums.FileExtEnum;
import com.jjhroy.blog.exception.BizException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.file.Files;
import java.util.Objects;

/**
 * @author ftz
 *
 * Windows本地上传策略
 *
 */
@Service("windowsUploadStrategyImpl")
public class WindowsUploadStrategyImpl extends AbstractUploadStrategyImpl  {

    /**
     * 本地路径
     */
    @Value("${upload.windowsLocal.path}")
    private String localPath;

    @Value("${upload.windowsLocal.url}")
    private String localUrl;

    @Override
    public Boolean exists(String filePath) {
        return new File(localPath + filePath).exists();
    }

    @Override
    public void upload(String path, String fileName, InputStream inputStream) throws IOException {
        // 判断目录是否存在
        File directory = new File(localPath + path);
        if (!directory.exists()) {
            if (!directory.mkdirs()) {
                throw new BizException("创建目录失败");
            }
        }
        // 写入文件
        File file = new File(localPath + path + fileName);
        String ext = "." + fileName.split("\\.")[1];
        switch (Objects.requireNonNull(FileExtEnum.getFileExt(ext))) {
            case MD:
            case TXT:
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                BufferedWriter writer = new BufferedWriter(new FileWriter(file));
                while (reader.ready()) {
                    writer.write((char) reader.read());
                }
                writer.flush();
                writer.close();
                reader.close();
                break;
            default:
                BufferedInputStream bis = new BufferedInputStream(inputStream);
                BufferedOutputStream bos = new BufferedOutputStream(Files.newOutputStream(file.toPath()));
                byte[] bytes = new byte[1024];
                int length;
                while ((length = bis.read(bytes)) != -1) {
                    bos.write(bytes, 0, length);
                }
                bos.flush();
                bos.close();
                bis.close();
                break;
        }
        inputStream.close();
    }


    @Override
    public String getFileAccessUrl(String filePath) {
        return localUrl+filePath;
    }






}

(6):controller层:更新用户头像为例:


    /**
     * 更新用户头像
     *
     * @param file 文件
     * @return {@link Result<String>} 头像地址
     */
    @ApiOperation(value = "更新用户头像")
    @ApiImplicitParam(name = "file", value = "用户头像", required = true, dataType = "MultipartFile")
    @PostMapping("/users/avatar")
    public Result<String> updateUserAvatar(MultipartFile file) {
        return Result.ok(userInfoService.updateUserAvatar(file));
    }

(7):userInfoService.updateUserAvatar层及其实现:

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String updateUserAvatar(MultipartFile file) {
        // 头像上传
        String avatar = uploadStrategyContext.executeUploadStrategy(file, FilePathEnum.AVATAR.getPath());
        // 更新用户信息
        UserInfo userInfo = UserInfo.builder()
                .id(UserUtils.getLoginUser().getUserInfoId())
                .avatar(avatar)
                .build();
        userInfoDao.updateById(userInfo);
        return avatar;
    }

(8):uploadStrategyContext.executeUploadStrategy:

在这里插入图片描述

package com.jjhroy.blog.strategy.context;

import com.jjhroy.blog.enums.UploadModeEnum;
import com.jjhroy.blog.strategy.UploadStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.Map;


/**
 * 上传策略上下文
 *
 * @author yezhiqiu
 * @date 2021/07/28
 */
@Service
public class UploadStrategyContext {
    /**
     * 上传模式
     */
    @Value("${upload.mode}")
    private String uploadMode;

    @Autowired
    private Map<String, UploadStrategy> uploadStrategyMap;

    /**
     * 执行上传策略
     *
     * @param file 文件
     * @param path 路径
     * @return {@link String} 文件地址
     */
    public String executeUploadStrategy(MultipartFile file, String path) {
        return uploadStrategyMap.get(UploadModeEnum.getStrategy(uploadMode)).uploadFile(file, path);
    }


    /**
     * 执行上传策略
     *
     * @param fileName    文件名称
     * @param inputStream 输入流
     * @param path        路径
     * @return {@link String} 文件地址
     */
    public String executeUploadStrategy(String fileName, InputStream inputStream, String path) {
        return uploadStrategyMap.get(UploadModeEnum.getStrategy(uploadMode)).uploadFile(fileName, inputStream, path);
    }

}

(9):抽象上传模板

在这里插入图片描述

(10)文件上传工具类:

package com.jjhroy.blog.util;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.codec.binary.Hex;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.util.Objects;

/**
 * 文件md5工具类
 *
 * @author yezhiqiu
 * @date 2021/07/28
 */
@Log4j2
public class FileUtils {

    /**
     * 获取文件md5值
     *
     * @param inputStream 文件输入流
     * @return {@link String} 文件md5值
     */
    public static String getMd5(InputStream inputStream) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("md5");
            byte[] buffer = new byte[8192];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                md5.update(buffer, 0, length);
            }
            return new String(Hex.encodeHex(md5.digest()));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 得到文件扩展名
     *
     * @param fileName 文件名称
     * @return {@link String} 文件后缀
     */
    public static String getExtName(String fileName) {
        if (StringUtils.isBlank(fileName)) {
            return "";
        }
        return fileName.substring(fileName.lastIndexOf("."));
    }

    /**
     * 转换file
     *
     * @param multipartFile 多部分文件
     * @return {@link File} file
     */
    public static File multipartFileToFile(MultipartFile multipartFile) {
        File file = null;
        try {
            String originalFilename = multipartFile.getOriginalFilename();
            String[] filename = Objects.requireNonNull(originalFilename).split("\\.");
            file = File.createTempFile(filename[0], filename[1]);
            multipartFile.transferTo(file);
            file.deleteOnExit();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }


    /**
     * 自动调节精度(经验数值)
     *
     * @param size 源图片大小
     * @return 图片压缩质量比
     */
    private static double getAccuracy(long size) {
        double accuracy;
        if (size < 900) {
            accuracy = 0.85;
        } else if (size < 2048) {
            accuracy = 0.6;
        } else if (size < 3072) {
            accuracy = 0.44;
        } else {
            accuracy = 0.4;
        }
        return accuracy;
    }

}

3.2:其余三种类似,只需要改变一下application.yml就好

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/54473.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Raspberry Pi 3 Model B+ (树莓派3B+)快速上手

文章目录一、硬件资源二、供电三、引脚说明四、Raspberry Pi OS1. 下载imager2. 选择操作系统3. 选择SD卡4. 烧写完成5. 启动6. 版本信息五、网络测试1. WiFi2. 以太网六、开启串口日志1. 硬件串口连接2. 修改config.txt配置3. 修改cmdline4. 测试一、硬件资源 下面是硬件资源图…

架构-三层架构:三层架构

概述 顾名思义&#xff0c;三层架构分为三层&#xff0c;分别是“数据访问层”、“业务逻辑层”、“表示层”。 数据访问层&#xff1a;数据访问层在作业过程中访问数据系统中的文件&#xff0c; 实现对数据库中数据的读取保存操作。 表示层&#xff1a;主要功能是 显示数据和…

李宁「向上」:不止缺一个FILA

文|螳螂观察 作者|易不二 随着卡塔尔世界杯拉开战幕&#xff0c;今年年初大幅下跌的阿迪和耐克&#xff0c;正在借助世界杯大放异彩。 据统计&#xff0c;在2022年的32强世界杯球衣中&#xff0c;耐克、阿迪、彪马三家品牌共包揽了80%。世界杯球衣是出镜率最高的广告载体&am…

Android基础之Fragment

目录前言一、Fragment简介二、Fragment的基础使用1.创建Fragment2.在Activity中加入Fragment&#xff08;1&#xff09;在Activity的layout.xml布局文件中静态添加&#xff08;2&#xff09;在Activity的.java文件中动态添加三、Fragment的基础实践应用1.应用过程详解2.代码总览…

Java JDK下载与安装教程

文章目录Java JDK 简介下载 JDK安装 JDKJava JDK 简介 JDK是 Java 语言的软件开发工具包&#xff0c;主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心&#xff0c;它包含了JAVA的运行环境&#xff08;JVMJava系统类库&#xff09;和JAVA工具。 万事开…

Flink系列文档-(YY11)-watermark工作机制

1 WaterMark生成工作机制 观察源码 /*** A WatermarkGenerator for situations where records are out of order, but you can place an upper* bound on how far the events are out of order. An out-of-order bound B means that once an event* with timestamp T was encou…

[附源码]Python计算机毕业设计SSM酒店管理系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

alertmanager 基于webhook-adapter插件实现企业微信机器人提醒服务

前言 Alertmanager处理客户端应用程序&#xff08;例如 Prometheus 服务器&#xff09;发送的警报。它负责删除重复数据、分组并将它们路由到正确的接收器集成&#xff0c;例如电子邮件、PagerDuty 或 OpsGenie。它还负责警报的静音和抑制。 前提要求 安装docker&#xff0c;…

分布式搜索引擎 ElasticSearch(ES)

一、初识elasticsearch 1.了解ES 1&#xff09;elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎&#xff0c;具备非常多强大功能&#xff0c;可以帮助我们从海量数据中快速找到需要的内容。elasticsearch结合kibana、Logstash、Beats&#xff0c;也就是elast…

基于SSH的周报管理系统

来公司的第一个实习项目&#xff0c;前端使用的是Freemark,刚开始上手比较复杂&#xff0c;慢慢摸索也算是圆满完成了&#xff0c;加油&#xff01;

LockSupport与线程中断

LockSupport与线程中断 线程中断机制 voidinterrupt()中断此线程static booleaninterrupted()获取当前线程中断标志位 true|falsebooleanisInterrupted()获取当前线程中断标志位true|false static boolean interrupted&#xff08;&#xff09;和boolean isInterrupted&#x…

【unity】安卓环境配置(踩坑整理)

一、基础环境配置 1、模块安装 可能报错&#xff1a;Currently selected scripting backend (IL2CPP) is notinstalled. 解决&#xff1a;部分项目依赖于IL2CPP&#xff0c;及WebGL组件&#xff0c;因此也需要勾上。 2、打开偏好设置 3、设置需要的VS版本 可能报错&#xf…

Linux动态库与静态库

Linux动态库与静态库 文章目录Linux动态库与静态库1.库的概念、种类与使用2.链接简述2.1 链接过程理解2.2 静态链接与动态链接概念2.3 静态链接与动态链接的例子3.动态库与静态库的生成方法3.1 静态库的生成3.2 静态库的打包3.2 静态库的使用3.3 动态库的生成3.4 动态库的打包3…

[附源码]JAVA毕业设计基于web的面向公众的食品安全知识系统(系统+LW)

[附源码]JAVA毕业设计基于web的面向公众的食品安全知识系统&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&…

设备发现:通向全面网络可见性的途径

想实现企业网络安全防护&#xff0c;它首先需要完全了解其网络中发生的所有事件。有了这种可见性&#xff0c;企业网络安全管理员可以分析用户在网络环境中进行了哪些危险的操作&#xff0c;并采取必要的应对措施来主动保护企业网络免受攻击。 日志取证 但是&#xff0c;如果攻…

Java 每日一练 (7)

Java每日一练(7) 单选 1. JAVA属于&#xff08; &#xff09;。   A 操作系统 B 办公软件 C 数据库系统 D 计算机语言 答案 &#xff1a; java 是属于一门语言&#xff0c;是 计算可以识别的语言&#xff0c; 所以 答案 D 2. 类声明中&#xff0c;声明抽象类的关键字是 ( …

9.HTTP协议

通信有三要素&#xff0c;分别是通信的主体(通信的双方是谁)&#xff0c;通信的内容&#xff0c;通信的方式(打电话&#xff0c;写信这种)| 通信协议是通信双方完成通信所必须遵守的规则和约定 网页内容叫做超文本(HyperText)&#xff0c;网页内容的传输协议叫做超文本传输协…

JDSU故障测试仪维修OTDR光时域反射仪维修MTS2000

应用范围&#xff1a;邮电通信工程与维护&#xff0c;有线电视工程与维护&#xff0c;光缆制造商&#xff0c;光纤综合布线系统。 功能特点&#xff1a; 结构紧凑&#xff0c;重量轻&#xff0c;高度集成 已经可以支持40多个应用模块 有IL/ORL、OTDR、PMD、CD 或WDM 插拔模…

忆享科技聚焦|数字经济、网络安全、5.5G、数字火炬手……热点资讯一览

“忆享聚焦”栏目第十期来啦&#xff01;本栏目汇集近期互联网最新资讯&#xff0c;聚焦前沿科技&#xff0c;关注行业发展动态&#xff0c;筛选高质量讯息&#xff0c;拓宽用户视野&#xff0c;让您以最低的时间成本获取最有价值的行业资讯。 目录 行业资讯 1. 工信部&#xf…

十三、Vue CLI(1)

本章概要 简介安装创建项目 vue create使用图形界面 在开发大型单页面应用时&#xff0c;需要考虑项目的组织结构、项目构建、部署、热加载、代码单元测试等多方面与核心业务逻辑无关的事情&#xff0c;对于项目中用到的构建工具、代码检查工具等还需要一遍一遍地重复配置。…