目录

1. 上传单个图片

业务方法

工具类

返回结果

2. 上传图片压缩包并解压到指定目录,和用户信息匹配

业务方法

工具类

常量

3. 读取本地磁盘图片

方式1:配置文件

方式2:修改yaml文件

方式3:使用三方工具,如:minio



1. 上传单个图片

业务方法

Controller层


Service层

//    /**
//     * 服务端口
//     */
//    @Value("${server.port}")
//    private String serverPort;
//    /**
//     * 在配置文件中配置的文件保存路径
//     */
//    @Value("${certif.img.storePath}")
//    private String imgStorePath;
    public AjaxResult uploadImg(MultipartFile multipartFile) {
        // 1. 校验
        if (multipartFile.isEmpty() || StringUtils.isBlank(multipartFile.getOriginalFilename())) {
            return AjaxResult.error("图片或图片名缺失");
        String contentType = multipartFile.getContentType();
        if (!contentType.contains("")) {
            return AjaxResult.error("图片类型缺失");
        // 2. 保存
        String originalFilename = multipartFile.getOriginalFilename();
        log.info("【上传图片】:name:{},type:{}", originalFilename, contentType);
        //处理图片
        //获取路径
        String filePath = imgStorePath;
        log.info("【上传图片】,图片保存路径:{}", filePath);
        try {
            ImageUtil.saveImg(multipartFile, filePath, originalFilename);
        } catch (IOException e) {
            log.info("【上传图片】失败,图片保存路径={}", filePath);
            return AjaxResult.error("【上传图片】失败");
        // 3.更新数据库(上传图片名称和证书编号一致)
        String certifNum = originalFilename.substring(0, originalFilename.lastIndexOf("."));
        CertifInfoDO certifInfoDO = new CertifInfoDO();
        certifInfoDO.setCertifNum(certifNum);
        String imageUrlPath = readUserImageUrl(originalFilename);
        certifInfoDO.setUserImageUrl(imageUrlPath);
        List<CertifInfoDO> certifInfoDOList = Arrays.asList(certifInfoDO);
        certifInfoMapper.batchInsertOrUpdateCertif(certifInfoDOList);
        return AjaxResult.success("【上传图片】成功");
    }


工具类


返回结果

import java.util.HashMap;
import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.utils.StringUtils;
 * 操作消息提醒
 * @author ruoyi
public class AjaxResult extends HashMap<String, Object>
    private static final long serialVersionUID = 1L;
    /** 状态码 */
    public static final String CODE_TAG = "code";
    /** 返回内容 */
    public static final String MSG_TAG = "msg";
    /** 数据对象 */
    public static final String DATA_TAG = "data";
     * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
    public AjaxResult()
     * 初始化一个新创建的 AjaxResult 对象
     * @param code 状态码
     * @param msg 返回内容
    public AjaxResult(int code, String msg)
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
     * 初始化一个新创建的 AjaxResult 对象
     * @param code 状态码
     * @param msg 返回内容
     * @param data 数据对象
    public AjaxResult(int code, String msg, Object data)
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
        if (StringUtils.isNotNull(data))
            super.put(DATA_TAG, data);
     * 返回成功消息
     * @return 成功消息
    public static AjaxResult success()
        return AjaxResult.success("操作成功");
     * 返回成功数据
     * @return 成功消息
    public static AjaxResult success(Object data)
        return AjaxResult.success("操作成功", data);
     * 返回成功消息
     * @param msg 返回内容
     * @return 成功消息
    public static AjaxResult success(String msg)
        return AjaxResult.success(msg, null);
     * 返回成功消息
     * @param msg 返回内容
     * @param data 数据对象
     * @return 成功消息
    public static AjaxResult success(String msg, Object data)
        return new AjaxResult(HttpStatus.SUCCESS, msg, data);
     * 返回错误消息
     * @return
    public static AjaxResult error()
        return AjaxResult.error("操作失败");
     * 返回错误消息
     * @param msg 返回内容
     * @return 警告消息
    public static AjaxResult error(String msg)
        return AjaxResult.error(msg, null);
     * 返回错误消息
     * @param msg 返回内容
     * @param data 数据对象
     * @return 警告消息
    public static AjaxResult error(String msg, Object data)
        return new AjaxResult(HttpStatus.ERROR, msg, data);
     * 返回错误消息
     * @param code 状态码
     * @param msg 返回内容
     * @return 警告消息
    public static AjaxResult error(int code, String msg)
        return new AjaxResult(code, msg, null);
}


2. 上传图片压缩包并解压到指定目录,和用户信息匹配

依赖包


业务方法

Controller层


Service层

//    /**
//     * 服务端口
//     */
//    @Value("${server.port}")
//    private String serverPort;
//    /**
//     * 在配置文件中配置的文件保存路径
//     */
//    @Value("${certif.img.storePath}")
//    private String imgStorePath;
     * @Title: 批量证书图片上传
     * @MethodName: uploadImgZip
     * @param zipFile
     * @Exception
     * @Description:
     * @author: 王延飞
    @Override
    public AjaxResult uploadImgZip(MultipartFile zipFile) throws IOException {
        // 1. 参数校验
        if (Objects.isNull(zipFile)) {
            return AjaxResult.error("【批量证书图片上传】缺少zip包");
        String fileContentType = zipFile.getContentType();
        if (!Constants.CONTENT_TYPE_ZIP.equals(fileContentType)
                && !Constants.CONTENT_TYPE_ZIP_COMPRESSED.equals(fileContentType)
            return AjaxResult.error("【批量证书图片上传】类型不是zip");
        // 2. 保存
        //将压缩包保存在指定路径
        String filePath = imgStorePath + File.separator + zipFile.getName();
        //保存到服务器
        boolean saveFile = FileUtils.saveFile(zipFile, filePath);
        if (!saveFile) {
            return AjaxResult.error("【批量证书图片上传】失败");
        // 3. 更新数据库
        InputStream in = new BufferedInputStream(new FileInputStream(filePath));
        ZipInputStream zin = new ZipInputStream(in);
        ZipEntry ze;
        ArrayList<CertifInfoDO> certifInfoDOS = new ArrayList<>();
        while ((ze = zin.getNextEntry()) != null) {
            if (ze.isDirectory()) {
            } else {
                String originalFilename = ze.getName();
                if (StringUtils.isBlank(originalFilename)) {
                    return AjaxResult.error("【批量证书图片上传】存在文件名缺失");
                String certifNum = originalFilename.substring(0, originalFilename.lastIndexOf("."));
                CertifInfoDO certifInfoDO = new CertifInfoDO();
                certifInfoDO.setCertifNum(certifNum);
                String imageUrlPath = readUserImageUrl(originalFilename);
                certifInfoDO.setUserImageUrl(imageUrlPath);
                certifInfoDOS.add(certifInfoDO);
        zin.closeEntry();
        certifInfoMapper.batchInsertOrUpdateCertif(certifInfoDOS);
        String destPath = imgStorePath + File.separator;
        // 4. 解压,并删除zip包
        boolean unPackZip = FileUtils.unPackZip(new File(filePath), "", destPath, true);
        if (unPackZip) {
            return AjaxResult.success("【批量证书图片上传解压】成功");
        } else {
            return AjaxResult.error("【批量证书图片上传解压】失败");
     * @Title: 图片路径
     * @MethodName: getUserImageUrl
     * @param originalFilename
     * @Return java.lang.String
     * @Exception
     * @Description:
     * @author: 王延飞
    private String readUserImageUrl(String originalFilename) {
        // http://localhost:8989/image/11
        StringBuilder imageUrl = new StringBuilder("http://");
        String hostAddress = null;
        try {
            hostAddress = Inet4Address.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            log.info("【图片路径】获取失败:{}", e);
            return null;
        String imageUrlPath = imageUrl.append(hostAddress)
                .append(":").append(serverPort)
                .append("/image/").append(originalFilename)
                .toString().trim();
        return imageUrlPath;
    }


工具类

import com.ruoyi.common.core.constant.Constants;
import net.lingala.zip4j.core.ZipFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
 * @Title: zip文件解压
 * @Description:
 * @author: 王延飞
 * @date: 2020/8/14 0014 10:25
 * @version V1.0
public class FileUtils {
    protected static Logger log = LoggerFactory.getLogger(FileUtils.class);
     * @Title: 文件保存
     * @MethodName: saveFile
     * @param file
     * @param path
     * @Return boolean
     * @Exception
     * @Description:
     * @author: 王延飞
     * @date: 2020/8/14 0014 11:04
    public static boolean saveFile(MultipartFile file, String path) {
        File desFile = new File(path);
        if (!desFile.getParentFile().exists()) {
            desFile.mkdirs();
        try {
            file.transferTo(desFile);
        } catch (IOException e) {
            log.error("【文件保存】异常,路径:{} ,异常信息:{} ", path, e);
            return false;
        return true;
     * @Title: 获取项目classpath路径
     * @MethodName: getApplicationPath
     * @param
     * @Return java.lang.String
     * @Exception
     * @Description:
     * @author: 王延飞
    public static String getApplicationPath() {
        //获取classpath
        ApplicationHome h = new ApplicationHome(CertifApplication.class);
        File jarF = h.getSource();
        return jarF.getParentFile() + File.separator;
     * zip文件解压
     * @param destPath 解压文件路径
     * @param zipFile  压缩文件
     * @param password 解压密码(如果有)
     * @param isDel 解压后删除
    public static boolean unPackZip(File zipFile, String password, String destPath, boolean isDel) {
        try {
            ZipFile zip = new ZipFile(zipFile);
            /*zip4j默认用GBK编码去解压*/
            zip.setFileNameCharset(Constants.UTF8);
            log.info("【文件解压】begin unpack zip file....");
            zip.extractAll(destPath);
            // 如果解压需要密码
            if (zip.isEncrypted()) {
                zip.setPassword(password);
        } catch (Exception e) {
            log.error("【文件解压】异常,路径:{} ,异常信息:{} ", destPath, e);
            return false;
        if (isDel) {
            zipFile.deleteOnExit();
        return true;
     * @Title: 读取文件内容
     * @MethodName:  readZipFile
     * @param file
     * @Return void
     * @Exception
     * @Description:
     * @author: 王延飞
     * @date:  2020/8/14 0014 20:26
    public static void readZipFile(String file) throws Exception {
        java.util.zip.ZipFile zf = new java.util.zip.ZipFile(file);
        InputStream in = new BufferedInputStream(new FileInputStream(file));
        ZipInputStream zin = new ZipInputStream(in);
        ZipEntry ze;
        while ((ze = zin.getNextEntry()) != null) {
            if (ze.isDirectory()) {
            } else {
                System.err.println("file - " + ze.getName());
        zin.closeEntry();
}


常量


3. 读取本地磁盘图片

按照如下方式修改后,就可以通过以下路径访问

http://localhost:8989/image/11.png


方式1:配置文件

package com.ruoyi.certif.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
 * @Title:  访问本地(磁盘)图片
 * @ClassName: com.ruoyi.certif.config.SourceConfiguration.java
 * @Description:
 * @author: 王延飞
 * @date:  2020/8/14 0014 15:26
 * @version V1.0
@Configuration
public class SourceConfiguration extends WebMvcConfigurerAdapter {
     * 在配置文件中配置的文件保存路径
    @Value("${certif.img.storePath}")
    private String imgStorePath;
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //其中/cetif/photo表示访问的前缀。"file:imgStorePath"是文件真实的存储路径(如:)
        // 访问路径如下:http://localhost:8088/cetif/photo/XXX.png
        registry.addResourceHandler("/cetif/photos/**").addResourceLocations("file:"+imgStorePath);
        super.addResourceHandlers(registry);
}


方式2:修改yaml文件

# Tomcat
server:
  port: 8989
# 图片存放路径
certif:
    storePath: D:\home\fly
# Spring
spring:
  # 访问图片路径为/image/**
    static-path-pattern: /image/**
  # 图片本地存放路径
  resources:
    static-locations: file:${certif.img.storePath}
  application:
    # 应用名称
    name: ruoyi-certif
  profiles:
    # 环境配置
    active: dev


方式3:使用三方工具,如:minio

参考连接: https://segmentfault.com/a/1190000012844836