From 75332ddd6aad6e99802675e79ec4b1828d74ae6f Mon Sep 17 00:00:00 2001 From: mashuai Date: Sat, 8 Mar 2025 10:32:21 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/controller/SysFileController.java | 31 ++- .../sgzb/system/service/SysFileService.java | 4 +- .../service/impl/SysFileServiceImpl.java | 65 ++---- .../sgzb/system/util/FileUploadUtils.java | 186 ++++++++++++++++++ 4 files changed, 223 insertions(+), 63 deletions(-) create mode 100644 sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/util/FileUploadUtils.java diff --git a/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/controller/SysFileController.java b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/controller/SysFileController.java index d3b2158..3bb8c47 100644 --- a/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/controller/SysFileController.java +++ b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/controller/SysFileController.java @@ -1,16 +1,18 @@ package com.bonus.sgzb.system.controller; -import com.bonus.sgzb.common.core.utils.StringHelper; +import cn.hutool.core.util.ObjectUtil; import com.bonus.sgzb.common.core.web.domain.AjaxResult; import com.bonus.sgzb.system.domain.FileInfo; import com.bonus.sgzb.system.service.SysFileService; import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; import org.apache.poi.util.IOUtils; import org.springframework.core.io.ResourceLoader; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.ServletOutputStream; @@ -25,6 +27,7 @@ import java.nio.charset.StandardCharsets; */ @RestController @RequestMapping("/sys/file") +@Slf4j public class SysFileController { @Resource @@ -36,23 +39,19 @@ public class SysFileController { @PostMapping("/upload") @ApiOperation(value = "文件上传") - public AjaxResult upload(HttpServletRequest request) { - String limitWords = request.getParameter("limitWords"); - FileInfo file = new FileInfo(); - try { - file = service.uploadFile(request); - if (limitWords != null && file.getWords() > Integer.parseInt(limitWords)){ - return AjaxResult.error("上传文件字数超出限制字数!"); - } - }catch (Exception e){ + public AjaxResult upload(MultipartFile file) { + try + { + // 上传并返回访问地址 + if (ObjectUtil.isEmpty(file)) { return AjaxResult.error("上传文件不能为空");} + FileInfo sysFile = service.uploadFile(file); + return AjaxResult.success(sysFile); + } + catch (Exception e) + { + log.error("上传文件失败", e); return AjaxResult.error(e.getMessage()); } - if (file != null && file.getId() != 0){ - return AjaxResult.success(file); - }else { - return AjaxResult.error("文件上传失败!"); - } - } @ApiOperation(value = "模板", httpMethod = "GET") diff --git a/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/service/SysFileService.java b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/service/SysFileService.java index b2af762..3a3fbdc 100644 --- a/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/service/SysFileService.java +++ b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/service/SysFileService.java @@ -15,11 +15,11 @@ public interface SysFileService { /** * 文件上传接口 - * @param request + * @param file * @return * @throws Exception */ - FileInfo uploadFile(HttpServletRequest request) throws Exception; + FileInfo uploadFile(MultipartFile file) throws Exception; /** * 上传头像 diff --git a/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/service/impl/SysFileServiceImpl.java b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/service/impl/SysFileServiceImpl.java index 5610094..f8cd76f 100644 --- a/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/service/impl/SysFileServiceImpl.java +++ b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/service/impl/SysFileServiceImpl.java @@ -1,15 +1,14 @@ package com.bonus.sgzb.system.service.impl; import cn.hutool.core.util.IdUtil; -import com.bonus.sgzb.common.core.constant.HttpStatus; import com.bonus.sgzb.common.core.utils.DateTimeHelper; import com.bonus.sgzb.common.core.utils.GlobalConstants; -import com.bonus.sgzb.common.core.web.domain.AjaxResult; import com.bonus.sgzb.common.security.utils.SecurityUtils; import com.bonus.sgzb.system.domain.FileInfo; import com.bonus.sgzb.system.mapper.FileInfoMapper; import com.bonus.sgzb.system.service.SysFileService; import com.bonus.sgzb.system.service.feign.FileClient; +import com.bonus.sgzb.system.util.FileUploadUtils; import lombok.extern.slf4j.Slf4j; import org.apache.poi.hwpf.extractor.WordExtractor; import org.apache.poi.openxml4j.util.ZipSecureFile; @@ -17,7 +16,6 @@ import org.apache.poi.xwpf.extractor.XWPFWordExtractor; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Primary; -import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest; @@ -45,6 +43,18 @@ public class SysFileServiceImpl implements SysFileService { @Value("${file.path}") private String localFilePath; + /** + * 资源映射路径 前缀 + */ + @Value("${file.prefix}") + public String localFilePrefix; + + /** + * 域名或本机访问地址 + */ + @Value("${file.domain}") + public String domain; + // 允许的文件格式 private static final List ALLOWED_EXTENSIONS = Arrays.asList("jpg", "jpeg", "txt", "png", "pdf", "docx", "doc", "xlsx", "xls"); @@ -59,48 +69,13 @@ public class SysFileServiceImpl implements SysFileService { * @throws Exception */ @Override - public FileInfo uploadFile(HttpServletRequest request) throws Exception { - FileInfo file = new FileInfo(); - StandardMultipartHttpServletRequest req = (StandardMultipartHttpServletRequest) request; - String photoType = req.getParameter("fileType"); - Long userId = SecurityUtils.getLoginUser().getUserid(); - HashMap map = getFile(req); - List items = (List) map.get("filePath"); - MultipartFile item = items.get(0); - // 获取文件后缀名 - String fileExtension = item.getOriginalFilename().substring(item.getOriginalFilename().lastIndexOf(".") + 1); - if (!ALLOWED_EXTENSIONS.contains(fileExtension.toLowerCase())) { - throw new Exception("不支持该文件格式"); - } - // 检查文件大小 - long fileSize = item.getSize(); - long maxSize = 20 * 1024 * 1024; // 20MB - if (fileSize > maxSize) { - throw new Exception("文件太大,请重新上传"); - } - try { - String url = saveFile(request, item, photoType); - //AjaxResult res = fileClient.uploadFile(item); - //String url = (String) res.get("msg"); - if (url != null) { - int words = getFileText(item); - String fileName = item.getOriginalFilename(); - String type = fileName.substring(fileName.lastIndexOf(".") + 1); - long size = item.getSize() / 1024 / 1024; - file.setFileName(fileName); - file.setFileUrl(url); - file.setCreator(userId.toString()); - file.setType(type); - file.setSize(size + "M"); - file.setWords(words); - file.setCreateBy(SecurityUtils.getLoginUser().getUserid().toString()); - file.setCreateTime(new Date()); - dao.insertFileInfo(file); - } - } catch (Exception e) { - e.printStackTrace(); - } - return file; + public FileInfo uploadFile(MultipartFile file) throws Exception { + String name = FileUploadUtils.upload(localFilePath, file); + String url = domain + localFilePrefix + name; + FileInfo fileInfo = new FileInfo(); + fileInfo.setFileUrl(url); + fileInfo.setFileName(name); + return fileInfo; } /** diff --git a/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/util/FileUploadUtils.java b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/util/FileUploadUtils.java new file mode 100644 index 0000000..03971d1 --- /dev/null +++ b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/util/FileUploadUtils.java @@ -0,0 +1,186 @@ +package com.bonus.sgzb.system.util; + +import com.bonus.sgzb.common.core.exception.file.FileException; +import com.bonus.sgzb.common.core.exception.file.FileNameLengthLimitExceededException; +import com.bonus.sgzb.common.core.exception.file.FileSizeLimitExceededException; +import com.bonus.sgzb.common.core.exception.file.InvalidExtensionException; +import com.bonus.sgzb.common.core.utils.DateUtils; +import com.bonus.sgzb.common.core.utils.StringUtils; +import com.bonus.sgzb.common.core.utils.file.FileTypeUtils; +import com.bonus.sgzb.common.core.utils.file.MimeTypeUtils; +import com.bonus.sgzb.common.core.utils.uuid.Seq; +import org.apache.commons.io.FilenameUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Objects; + +/** + * 文件上传工具类 + * + * @author ruoyi + */ +public class FileUploadUtils +{ + /** + * 默认大小 50M + */ + public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024; + + /** + * 默认的文件名最大长度 100 + */ + public static final int DEFAULT_FILE_NAME_LENGTH = 100; + + /** + * 根据文件路径上传 + * + * @param baseDir 相对应用的基目录 + * @param file 上传的文件 + * @return 文件名称 + * @throws IOException + */ + public static final String upload(String baseDir, MultipartFile file) throws IOException + { + try + { + return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); + } + catch (FileException fe) + { + throw new IOException(fe.getDefaultMessage(), fe); + } + catch (Exception e) + { + throw new IOException(e.getMessage(), e); + } + } + + /** + * 文件上传 + * + * @param baseDir 相对应用的基目录 + * @param file 上传的文件 + * @param allowedExtension 上传文件类型 + * @return 返回上传成功的文件名 + * @throws FileSizeLimitExceededException 如果超出最大大小 + * @throws FileNameLengthLimitExceededException 文件名太长 + * @throws IOException 比如读写文件出错时 + * @throws InvalidExtensionException 文件校验异常 + */ + public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension) + throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException, + InvalidExtensionException + { + int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length(); + if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) + { + throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH); + } + + assertAllowed(file, allowedExtension); + + String fileName = extractFilename(file); + + String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath(); + file.transferTo(Paths.get(absPath)); + return getPathFileName(fileName); + } + + /** + * 编码文件名 + */ + public static final String extractFilename(MultipartFile file) + { + return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(), + FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.UPLOAD_SEQ_TYPE), FileTypeUtils.getExtension(file)); + } + + private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException + { + File desc = new File(uploadDir + File.separator + fileName); + + if (!desc.exists()) + { + if (!desc.getParentFile().exists()) + { + desc.getParentFile().mkdirs(); + } + } + return desc.isAbsolute() ? desc : desc.getAbsoluteFile(); + } + + private static final String getPathFileName(String fileName) throws IOException + { + String pathFileName = "/" + fileName; + return pathFileName; + } + + /** + * 文件大小校验 + * + * @param file 上传的文件 + * @throws FileSizeLimitExceededException 如果超出最大大小 + * @throws InvalidExtensionException 文件校验异常 + */ + public static final void assertAllowed(MultipartFile file, String[] allowedExtension) + throws FileSizeLimitExceededException, InvalidExtensionException + { + long size = file.getSize(); + if (size > DEFAULT_MAX_SIZE) + { + throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024); + } + + String fileName = file.getOriginalFilename(); + String extension = FileTypeUtils.getExtension(file); + if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) + { + if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) + { + throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension, + fileName); + } + else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) + { + throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension, + fileName); + } + else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) + { + throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension, + fileName); + } + else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) + { + throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension, + fileName); + } + else + { + throw new InvalidExtensionException(allowedExtension, extension, fileName); + } + } + } + + /** + * 判断MIME类型是否是允许的MIME类型 + * + * @param extension 上传文件类型 + * @param allowedExtension 允许上传文件类型 + * @return true/false + */ + public static final boolean isAllowedExtension(String extension, String[] allowedExtension) + { + for (String str : allowedExtension) + { + if (str.equalsIgnoreCase(extension)) + { + return true; + } + } + return false; + } +} \ No newline at end of file