目录
1. 上传单个图片
业务方法
Controller层
@PostMapping("/upload") public AjaxResult uploadImg(@RequestParam("file") MultipartFile multipartFile) { AjaxResult result = certifInfoService.uploadImg(multipartFile); return result; }
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 org.springframework.web.multipart.MultipartFile; import java.io.*; public class ImageUtil { /** * 保存文件,直接以multipartFile形式 * @param multipartFile * @param path 文件保存绝对路径 * @param fileName 文件名 * @return 返回路径+文件名 * @throws IOException */ public static String saveImg(MultipartFile multipartFile, String path, String fileName) throws IOException { File file = new File(path); if (!file.exists()) { file.mkdirs(); } FileInputStream fileInputStream = (FileInputStream) multipartFile.getInputStream(); String fileFullPath = path + File.separator + fileName; BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileFullPath)); byte[] bs = new byte[1024]; int len; while ((len = fileInputStream.read(bs)) != -1) { bos.write(bs, 0, len); } bos.flush(); bos.close(); return fileFullPath; } }
返回结果
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. 上传图片压缩包并解压到指定目录,和用户信息匹配
依赖包
<dependency> <groupId>net.lingala.zip4j</groupId> <artifactId>zip4j</artifactId> <version>1.3.2</version> </dependency>
业务方法
Controller层
@PostMapping("/zip") public AjaxResult uploadImgZip(@RequestParam("file") MultipartFile zipFile) throws IOException { AjaxResult result = certifInfoService.uploadImgZip(zipFile); return result; }
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(); } }
常量
/** * 通用常量信息 * */ public class Constants { /** * UTF-8 字符集 */ public static final String UTF8 = "UTF-8"; /** * GBK 字符集 */ public static final String GBK = "GBK"; /** * http请求 */ public static final String HTTP = "http://"; /** * https请求 */ public static final String HTTPS = "https://"; /** * 文件类型 <application/zip> */ public static final String CONTENT_TYPE_ZIP = "application/zip"; /** * 文件类型 <application/x-zip-compressed> */ public static final String CONTENT_TYPE_ZIP_COMPRESSED = "application/x-zip-compressed"; }
3. 读取本地磁盘图片
按照如下方式修改后,就可以通过以下路径访问
方式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: img: storePath: D:\home\fly # Spring spring: # 访问图片路径为/image/** mvc: 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