Springboot文件上传-demo----------dev(开发)环境和pro(生产)环境

Springboot之文件上传

一、父pom.xml导入相关依赖
commons-lang3工具依赖和文件上传核心依赖

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>${fileupload.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>

在这里插入图片描述
二、编写yml配置文件,分dev和pro两个环境
application-dev.yml

# 自定义fileupload的属性
fileupload:
# 开发环境上传文件的根路径就为项目路径下的upload目录
  root-path: "D:\\IdeaProjects\\study\\springboot-demo\\springboot-fileupload\\upload"
  # 图片上传的相对路径
  image-path: /imgs
  # pdf文件上传的相对路径
  pdf-path: /pdf
  # 其他文件的相对路径
  other-path: /other
  # 文件名的前缀
  prefix-img: IMG_

spring:
  datasource:
    #===========JDBC 配置===========
    url: jdbc:mysql://47.100.57.52:3310/db_test?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
    # 初始化线程池数量  最大数  最小数
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
    # 驱动包 8.0以上的配置
    # =========== druid 连接池配置===========
    druid:
      initial-size: 5
      max-active: 20
      min-idle: 3
      # 配置获取连接等待超时的时间 单位毫秒
      max-wait: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      time-between-eviction-runs-millis: 60000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      min-evictable-idle-time-millis: 300000
      validation-query: select
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      # 打开PSCache,并且指定每个连接上PSCache的大小
      pool-prepared-statements: true
      #      配置监控统计拦截器 日志配置  防火墙
      #      stat监控数据库性能
      #      wall  用于防火墙
      #      日志 slf4j logback
      #      log4j
      #      log4j2
      # 配置多个英文逗号分隔
      filters: stat,wall,slf4j
      max-pool-prepared-statement-per-connection-size: 20
      # 合并多个DruidDataSource的监控数据
      use-global-data-source-stat: true
      # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
      connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
      # ===========监控配置===========
      # WebStatFilter配置,说明请参考Druid Wiki,配置_配置WebStatFilter
      web-stat-filter:
        #是否启用StatFilter默认值false
        enabled: true
        # 拦截所有的
        url-pattern: /*
        # 排除一些不必要的url,比如*:js/*等等:
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico, /druid/*"
        # 关闭和开启session 统计功能 默认关闭
        #        session-stat-enable: true
        # sessionStatMaxCount是1000个
        #        session-stat-max-count: 1000
        # 配置principalSessionName,使得druid能够知道当前的session的用户是谁
        #        principal-session-name:
        # StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
      stat-view-servlet:
        # 是否启用StatViewServlet默认值true
        enabled: true
        url-pattern: /druid/*
        # 界面上有一个重置功能 执行这个操作之后,会导致所有计数器清零,重新计数 建议false
        reset-enable: false
        # 登录的后台的用户名,密码
        login-username: admin
        login-password: admin
        # 访问控制,可以配置allow和deny这两个参数
        # 配置格式 ip或者ip/子网掩码(24) 例如   192.168.2.112 ,192.168.2.112/24
        # 注意 由于匹配规则不支持IPV6,配置了allow或者deny之后,会导致IPV6无法访问。
        # allow:
        # deny:

application-pro.yml

#  部署 静态文件  /ninx静态文件
fileupload:
# 部署环境下文件上传的根路径
  root-path: /opt/uploads
# 部署环境下图片上传的相对路径
  image-path: /imgs
# 部署环境下pdf文件上传的相对路径
  pdf-path: /pdf
# 部署环境下其他文件上传的相对路径
  other-path: /other
# 上传的图片文件的文件名前缀
  prefix-img: IMG_

server:
  port: 8080

spring:
  datasource:
    #===========JDBC 配置===========
    url: jdbc:mysql://119.23.190.71:3307/db_upload?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
    # 初始化线程池数量  最大数  最小数
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
    # 驱动包 8.0以上的配置
    # =========== druid 连接池配置===========
    druid:
      initial-size: 5
      max-active: 20
      min-idle: 3
      # 配置获取连接等待超时的时间 单位毫秒
      max-wait: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      time-between-eviction-runs-millis: 60000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      min-evictable-idle-time-millis: 300000
      validation-query: select
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      # 打开PSCache,并且指定每个连接上PSCache的大小
      pool-prepared-statements: true
      #      配置监控统计拦截器 日志配置  防火墙
      #      stat监控数据库性能
      #      wall  用于防火墙
      #      日志 slf4j logback
      #      log4j
      #      log4j2
      # 配置多个英文逗号分隔
      filters: stat,wall,slf4j
      max-pool-prepared-statement-per-connection-size: 20
      # 合并多个DruidDataSource的监控数据
      use-global-data-source-stat: true
      # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
      connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
      # ===========监控配置===========
      # WebStatFilter配置,说明请参考Druid Wiki,配置_配置WebStatFilter
      web-stat-filter:
        #是否启用StatFilter默认值false
        enabled: true
        # 拦截所有的
        url-pattern: /*
        # 排除一些不必要的url,比如*:js/*等等:
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico, /druid/*"
        # 关闭和开启session 统计功能 默认关闭
        #        session-stat-enable: true
        # sessionStatMaxCount是1000个
        #        session-stat-max-count: 1000
        # 配置principalSessionName,使得druid能够知道当前的session的用户是谁
        #        principal-session-name:
        # StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
      stat-view-servlet:
        # 是否启用StatViewServlet默认值true
        enabled: true
        url-pattern: /druid/*
        # 界面上有一个重置功能 执行这个操作之后,会导致所有计数器清零,重新计数 建议false
        reset-enable: false
        # 登录的后台的用户名,密码
        login-username: admin
        # 真实开发环境请把密码设置得复杂些
        login-password: admin
        # 访问控制,可以配置allow和deny这两个参数
        # 配置格式 ip或者ip/子网掩码(24) 例如   192.168.2.112 ,192.168.2.112/24
        # 注意 由于匹配规则不支持IPV6,配置了allow或者deny之后,会导致IPV6无法访问。
        # allow:
        # deny:

三、编写docker-compose.yml

# 指定docker-compose版本
version: '3'
# 服务
services:
  # 服务名
  file-upload:
    container_name: file-upload
    # 根据Dockerfile构建镜像
    build: ./
    # 映射数据卷
    volumes:
      - /opt/uploads/:/opt/uploads/
    # 映射端口
    ports:
      - 8081:8080

  # Nginx服务器,专门处理静态资源!
  nginx-server:
    # 镜像
    image: nginx
    # 指定一个容器名
    container_name: nginx-container
    # 映射数据卷
    volumes:
      - /opt/uploads/:/usr/share/nginx/html/
    # 映射端口
    ports:
      - 80:80

四、编写Dockerfile

# 指定基础镜像
FROM ubuntu:18.04
# 移动jdk到/usr/local/java目录下
ADD jdk-8u221-linux-x64.tar.gz /usr/local/java/
# 配置jdk环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_221
ENV CLASSPATH $JAVA_HOME/lib;$JAVA_HOME/jre/lib
ENV PATH $PATH:$JAVA_HOME/bin
# 把项目jar包复制到指定目录
ADD ./target/*.jar /app.jar
# 容器启动时候执行的命令
CMD ["java","-jar","app.jar"]

五、编写主程序
FileUploadsUtils 实现文件上传的工具类

package com.qf.zsm.springbootfileupload.utils;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

@Component
public class FileUploadUtils {
    //注入FileUploadProperties
    @Resource
    FileUploadProperties fileUploadProperties;

    /**
     *
     * @return imageRootPath 文件上传的相对路径
     * imgs/20191101/
     */
    public String getImagePath(){
        String imageImagePath = fileUploadProperties.getImagePath()+
                File.separator+ DateFormatUtils.format(new Date(),"yyyyMMdd");
        return imageImagePath;
    }

    /**
     *
     * @param prefix 上传后将文件重命名的前缀
     * @param oldFileName 上传后将文件重命名的主文件名,为防止名冲突,通常以当前时间为名以保证名字唯一
     * @return 上传后的新文件名
     */
    public String getFileName(String prefix,String oldFileName){
        //截取上传的文件的后缀名     .jpg   .png  等
        String suffix = oldFileName.substring(oldFileName.indexOf("."));
        return prefix+DateFormatUtils.format(new Date(),"yyyyMMddHHmmss")+suffix;
    }

    /**
     * 上传文件的方法
     * @param is 上传的文件的二进制输入流
     * @param file 上传的文件的保存的位置
     */
    public void saveFile(InputStream is,File file) throws IOException {
        //路径不存在就创建
        FileUtils.touch(file);
        //把要上传的文件输入流copy进file路径
        FileUtils.copyInputStreamToFile(is,file);
    }

    /**
     * 调用上传文件方法saveFile()并返回存储在数据库中的相对路径
     * @param multipartFile 上传的文件
     * @return 存储在的数据库的图片相对路径
     */
    public String saveImageFile(MultipartFile multipartFile) throws IOException {
        String imagePath = getImagePath();
        String fileName = getFileName(fileUploadProperties.getPrefixImg(),
                multipartFile.getOriginalFilename());
        //保存在数据库的图片的相对路径
        String dbImagePath = imagePath+File.separator+fileName;
        //本地跑项目上传文件的路径为rootPath+相对路径  远程服务器跑上传到相对路径
        // imgs/201911xxx/xxx.jpg
        File filePath = new File(fileUploadProperties.getRootPath()+dbImagePath);
        saveFile(multipartFile.getInputStream(),filePath);
        return dbImagePath;
    }
}

FileUploadProperties 获取yml文件中自定义属性的类

package com.qf.zsm.springbootfileupload.utils;


import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

// 获取application-xxx.yml配置文件中的自定义属性
@Component
@ConfigurationProperties(prefix = "fileupload")
@Data
public class FileUploadProperties {
    private String rootPath;
    private String imagePath;
    private String pdfPath;
    private String otherPath;
    private String prefixImg;
}

FileUploadServiceImpl 文件上传Service接口实现类(Service自己写一下)

package com.qf.zsm.springbootfileupload.service.impl;

import com.qf.zsm.springbootfileupload.service.FileUploadService;
import com.qf.zsm.springbootfileupload.utils.FileUploadUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;

@Service
public class FileUploadServiceImpl implements FileUploadService {
// 注入FileUploadUtils
    @Resource
    FileUploadUtils fileUploadUtils;

    @Override
    public String fileUploadImage(MultipartFile multipartFile) throws IOException {
        String imageFilePath = fileUploadUtils.saveImageFile(multipartFile);
        return imageFilePath;
    }
}

FileUploadController

package com.qf.zsm.springbootfileupload.controller;

import com.qf.zsm.springbootfileupload.service.FileUploadService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;

@RestController
@RequestMapping("fileUpload")
public class FileUploadController {
    @Resource
    FileUploadService fileUploadService;

    @RequestMapping(value = "/fileUploadImage",method = RequestMethod.POST)
    public String fileUploadImage(@RequestParam("image")MultipartFile multipartFile) throws IOException {
        String imagePath = fileUploadService.fileUploadImage(multipartFile);
        return imagePath;
    }
}

六、打包工程。拷贝一份jdk和docker-compose.yml和Dockerfile都放在项目根目录下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以上操作完成后只需要等docker-compose.yml文件构建完成!

七、测试
注意:一定要在application.yml配置文件中指定生效的yml文件
在这里插入图片描述
本地启动项目(指定yml生效文件为dev环境),利用PostMan工具去模拟Post请求(请求Controller的Mapping路径)传一张图片上去,
在这里插入图片描述
会发现本地项目的根路径已经按预想的一样成功上传了图片!
在这里插入图片描述
远程服务器上启动项目(指定yml生效文件为pro环境),利用PostMan工具去模拟Post请求(请求Controller的Mapping路径)传一张图片上去,一样的操作步骤,只需要把ip改成远程服务器的ip
在这里插入图片描述
可以看到图片已经成功上传到了远程服务器并且成功映射到了nginx服务器的静态资源路径下!
在这里插入图片描述
接下来,见证奇迹的一刻,去访问我们的nginx服务器这张图片静态资源,成功访问!
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值