From dd0a419daf628e99b8e4fa441d523433312a4601 Mon Sep 17 00:00:00 2001 From: Raod <1130305001@qq.com> Date: Fri, 2 Sep 2022 15:16:25 +0800 Subject: [PATCH] gaea oss --- report-core/pom.xml | 12 + .../gaea/business/code/ResponseCode.java | 3 +- .../impl/ReportDashboardServiceImpl.java | 16 +- .../modules/file/service/GaeaFileService.java | 7 + .../service/impl/GaeaFileServiceImpl.java | 235 +++++++++--------- .../service/impl/ReportExcelServiceImpl.java | 4 +- .../template/gaea/business/util/FileUtil.java | 92 +++++-- .../src/main/resources/bootstrap-dev.yml | 15 +- .../src/main/resources/bootstrap-prod.yml | 4 - report-core/src/main/resources/bootstrap.yml | 34 ++- .../resources/i18n/messages_en_US.properties | 3 +- .../resources/i18n/messages_zh_CN.properties | 3 +- 12 files changed, 256 insertions(+), 172 deletions(-) diff --git a/report-core/pom.xml b/report-core/pom.xml index 1ca9263f..7b2b59cd 100644 --- a/report-core/pom.xml +++ b/report-core/pom.xml @@ -61,6 +61,12 @@ test + + org.springframework + spring-mock + 2.0.8 + + org.springframework.cloud spring-cloud-context @@ -85,6 +91,12 @@ + + com.anji-plus + spring-boot-starter-gaea-oss + 2.0.5.RELEASE + + com.baomidou mybatis-plus-boot-starter diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/code/ResponseCode.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/code/ResponseCode.java index f0fe7039..0cefc8b1 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/code/ResponseCode.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/code/ResponseCode.java @@ -118,7 +118,8 @@ public interface ResponseCode { String FILE_SUFFIX_UNSUPPORTED = "2002"; String FILE_UPLOAD_ERROR = "2003"; String FILE_ONT_EXSIT = "2004"; - String LIST_IS_EMPTY = "2005"; + String FILE_OPERATION_FAILED = "file.operation.failed"; + String PUSHCODE_NEED_UNIQUE = "3001"; String RECEIVER_IS_EMPTY = "3002"; String DATA_SOURCE_CONNECTION_FAILED = "4001"; diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dashboard/service/impl/ReportDashboardServiceImpl.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dashboard/service/impl/ReportDashboardServiceImpl.java index fd3f2117..f6d7811b 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dashboard/service/impl/ReportDashboardServiceImpl.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dashboard/service/impl/ReportDashboardServiceImpl.java @@ -80,13 +80,13 @@ public class ReportDashboardServiceImpl implements ReportDashboardService, Initi @Autowired private ReportService reportService; - @Value("${customer.file.downloadPath:''}") + @Value("${spring.gaea.subscribes.oss.downloadPath:}") private String fileDownloadPath; - @Value("${customer.file.dist-path:''}") + @Value("${customer.file.tmp-path:.}") private String dictPath; - private final static String ZIP_PATH = "/zip/"; + private final static String ZIP_PATH = "/tmp_zip/"; private final static String JSON_PATH = "dashboard.json"; private Map queryServiceImplMap = new HashMap<>(); @@ -395,13 +395,9 @@ public class ReportDashboardServiceImpl implements ReportDashboardService, Initi queryWrapper.eq(GaeaFile::getFileId, fileName); GaeaFile gaeaFile = gaeaFileService.selectOne(queryWrapper); if (null != gaeaFile) { - String fileType = gaeaFile.getFileType(); - path = path + "/image/" + fileName + "." + fileType; - //path = /app/disk/upload/zip/UUID/image - - //原始文件的路径 - String filePath = gaeaFile.getFilePath(); - FileUtil.copyFileUsingFileChannels(filePath, path); + byte[] file = gaeaFileService.getFile(gaeaFile.getFileId()); + path = path + "/image/"; + FileUtil.byte2File(file, path, gaeaFile.getFileId().concat(".").concat(gaeaFile.getFileType())); } } diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/file/service/GaeaFileService.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/file/service/GaeaFileService.java index 4082ca7e..9cceea1e 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/file/service/GaeaFileService.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/file/service/GaeaFileService.java @@ -54,4 +54,11 @@ public interface GaeaFileService extends GaeaBaseService download(HttpServletRequest request, HttpServletResponse response, String fileId); + + /** + * 获取文件 + * @param fileId + * @return + */ + byte[] getFile(String fileId); } diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/file/service/impl/GaeaFileServiceImpl.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/file/service/impl/GaeaFileServiceImpl.java index 0d1de057..e45b6dba 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/file/service/impl/GaeaFileServiceImpl.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/file/service/impl/GaeaFileServiceImpl.java @@ -4,59 +4,51 @@ import com.anji.plus.gaea.constant.BaseOperationEnum; import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper; import com.anji.plus.gaea.exception.BusinessException; import com.anji.plus.gaea.exception.BusinessExceptionBuilder; +import com.anji.plus.gaea.oss.exceptions.GaeaOSSException; +import com.anji.plus.gaea.oss.exceptions.GaeaOSSTypeLimitedException; +import com.anji.plus.gaea.oss.ossbuilder.GaeaOSSTemplate; +import com.anji.plus.gaea.oss.utils.ResponseUtil; import com.anjiplus.template.gaea.business.code.ResponseCode; import com.anjiplus.template.gaea.business.modules.file.dao.GaeaFileMapper; import com.anjiplus.template.gaea.business.modules.file.entity.GaeaFile; import com.anjiplus.template.gaea.business.modules.file.service.GaeaFileService; -import com.anjiplus.template.gaea.business.modules.file.util.FileUtils; -import com.anjiplus.template.gaea.business.modules.file.util.StringPatternUtil; -import com.anjiplus.template.gaea.business.util.FileUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.apache.http.entity.ContentType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.CacheControl; -import org.springframework.http.MediaType; +import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.http.ResponseEntity; +import org.springframework.mock.web.MockMultipartFile; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.transaction.interceptor.TransactionAspectSupport; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Arrays; +import java.io.FileInputStream; import java.util.List; import java.util.UUID; -import java.util.stream.Collectors; /** - * (GaeaFile)ServiceImpl - * - * @author peiyanni - * @since 2021-02-18 14:48:26 + * 文件管理服务实现 + * @author: Raod + * @since: 2022-08-31 */ @Service @Slf4j +@RefreshScope public class GaeaFileServiceImpl implements GaeaFileService { - @Value("${customer.file.dist-path:''}") - private String dictPath; - - @Value("${customer.file.white-list:''}") - private String whiteList; - - @Value("${customer.file.excelSuffix:''}") - private String excelSuffix; - - @Value("${customer.file.downloadPath:''}") + @Value("${spring.gaea.subscribes.oss.downloadPath:''}") private String fileDownloadPath; + @Autowired + private GaeaOSSTemplate gaeaOSSTemplate; + @Autowired private GaeaFileMapper gaeaFileMapper; @@ -69,65 +61,60 @@ public class GaeaFileServiceImpl implements GaeaFileService { @Override @Transactional(rollbackFor = Exception.class) public GaeaFile upload(MultipartFile multipartFile, File file, String customFileName) { - try { - String fileName = ""; - if (null != multipartFile) { - fileName = multipartFile.getOriginalFilename(); - }else { - fileName = file.getName(); - } + String originalFilename = multipartFile.getOriginalFilename(); - if (StringUtils.isBlank(fileName)) { - throw BusinessExceptionBuilder.build(ResponseCode.FILE_EMPTY_FILENAME); - } + if (StringUtils.isBlank(originalFilename)) { + throw BusinessExceptionBuilder.build(ResponseCode.FILE_EMPTY_FILENAME); + } + // 文件后缀 .png + String suffixName = originalFilename.substring(originalFilename.lastIndexOf(".")); + // 生成文件唯一性标识 + String fileId; + if (StringUtils.isBlank(customFileName)) { + fileId = UUID.randomUUID().toString(); + } else { + fileId = customFileName; + } + // 生成在oss中存储的文件名 402b6193e70e40a9bf5b73a78ea1e8ab.png + String fileObjectName = fileId + suffixName; + // 生成链接通过fileId http访问路径 http://10.108.3.121:9089/meta/file/download/402b6193e70e40a9bf5b73a78ea1e8ab + String urlPath = fileDownloadPath + "/" + fileId; + + // 上传文件 + try{ + gaeaOSSTemplate.uploadFileByInputStream(multipartFile, fileObjectName); + }catch (GaeaOSSTypeLimitedException e){ + log.error("上传失败GaeaOSSTypeLimitedException", e); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_SUFFIX_UNSUPPORTED, e.getMessage()); + }catch (GaeaOSSException e){ + log.error("上传失败GaeaOSSException", e); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_UPLOAD_ERROR, e.getMessage()); + } - String suffixName = fileName.substring(fileName.lastIndexOf(".")); - String fileInstruction = fileName.substring(0, fileName.lastIndexOf(".")); - //白名单校验(不区分大小写) - List list = new ArrayList<>(Arrays.asList(whiteList.split("\\|"))); - list.addAll(list.stream().map(String::toUpperCase).collect(Collectors.toList())); - if (!list.contains(suffixName)) { - throw BusinessExceptionBuilder.build(ResponseCode.FILE_SUFFIX_UNSUPPORTED); - } - // 生成文件唯一性标识 - String fileId; - if (StringUtils.isBlank(customFileName)) { - fileId = UUID.randomUUID().toString(); - } else { - fileId = customFileName; - } - String newFileName = fileId + suffixName; - // 本地文件保存路径 - String filePath = dictPath + newFileName; - String urlPath = fileDownloadPath + "/" + fileId; - - GaeaFile gaeaFile = new GaeaFile(); - gaeaFile.setFilePath(filePath); - gaeaFile.setFileId(fileId); - gaeaFile.setUrlPath(urlPath); - gaeaFile.setFileType(suffixName.replace(".", "")); - gaeaFile.setFileInstruction(fileInstruction); - gaeaFileMapper.insert(gaeaFile); - - //写文件 将文件保存/app/dictPath/upload/下 - java.io.File dest = new java.io.File(dictPath + newFileName); - java.io.File parentFile = dest.getParentFile(); - if (!parentFile.exists()) { - parentFile.mkdirs(); - } - if (null != multipartFile) { - multipartFile.transferTo(dest); - }else { - FileUtil.copyFileUsingFileChannels(file, dest); - } - // 将完整的http访问路径返回 - return gaeaFile; - } catch (BusinessException e){ - throw BusinessExceptionBuilder.build(e.getCode()); - }catch (Exception e) { - log.error("file upload error", e); - throw BusinessExceptionBuilder.build(ResponseCode.FILE_UPLOAD_ERROR); + // 保存到文件管理中 + GaeaFile gaeaFile = new GaeaFile(); + gaeaFile.setFileId(fileId); + gaeaFile.setFilePath(fileObjectName); + gaeaFile.setUrlPath(urlPath); + gaeaFile.setFileType(suffixName.replace(".", "")); + gaeaFile.setFileInstruction(originalFilename); + insert(gaeaFile); + + return gaeaFile; + } + + private MultipartFile getMultipartFile(File file){ + FileInputStream fileInputStream; + MultipartFile multipartFile; + try { + fileInputStream = new FileInputStream(file); + multipartFile = new MockMultipartFile(file.getName(),file.getName(), + ContentType.APPLICATION_OCTET_STREAM.toString(),fileInputStream); + } catch (Exception e) { + log.error("file转MultipartFile失败", e); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } + return multipartFile; } /** @@ -150,52 +137,73 @@ public class GaeaFileServiceImpl implements GaeaFileService { */ @Override public GaeaFile upload(File file, String customFileName) { - return upload(null, file, customFileName); + return upload(getMultipartFile(file)); } @Override public ResponseEntity download(HttpServletRequest request, HttpServletResponse response, String fileId) { try { - String userAgent = request.getHeader("User-Agent"); - boolean isIeBrowser = userAgent.indexOf("MSIE") > 0; - //根据fileId,从gaea_file中读出filePath + // fileId必填 + if(StringUtils.isBlank(fileId)){ + throw BusinessExceptionBuilder.build(ResponseCode.FILE_ONT_EXSIT); + } + // 根据fileId,从gaea_file中读出filePath LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(); queryWrapper.eq(GaeaFile::getFileId, fileId); GaeaFile gaeaFile = gaeaFileMapper.selectOne(queryWrapper); if (null == gaeaFile) { throw BusinessExceptionBuilder.build(ResponseCode.FILE_ONT_EXSIT); } - //解析文件路径、文件名和后缀 - String filePath = gaeaFile.getFilePath(); - if (StringUtils.isBlank(filePath)) { + + String userAgent = request.getHeader("User-Agent"); + boolean isIEBrowser = userAgent.indexOf("MSIE") > 0; + // 在oss中存储的文件名 402b6193e70e40a9bf5b73a78ea1e8ab.png + String fileObjectName = gaeaFile.getFilePath(); + String originalFilename = gaeaFile.getFileInstruction(); + if (StringUtils.isBlank(fileObjectName) || StringUtils.isBlank(originalFilename)) { throw BusinessExceptionBuilder.build(ResponseCode.FILE_ONT_EXSIT); } - String filename = filePath.substring(filePath.lastIndexOf(File.separator)); - String fileSuffix = filename.substring(filename.lastIndexOf(".")); - - //根据文件后缀来判断,是显示图片\视频\音频,还是下载文件 - File file = new File(filePath); - ResponseEntity.BodyBuilder builder = ResponseEntity.ok(); - builder.contentLength(file.length()); - if (StringPatternUtil.stringMatchIgnoreCase(fileSuffix, "(.png|.jpg|.jpeg|.bmp|.gif|.icon)")) { - builder.cacheControl(CacheControl.noCache()).contentType(MediaType.IMAGE_PNG); - } else if (StringPatternUtil.stringMatchIgnoreCase(fileSuffix, "(.flv|.swf|.mkv|.avi|.rm|.rmvb|.mpeg|.mpg|.ogg|.ogv|.mov|.wmv|.mp4|.webm|.wav|.mid|.mp3|.aac)")) { - builder.header("Content-Type", "video/mp4; charset=UTF-8"); - } else { - //application/octet-stream 二进制数据流(最常见的文件下载) - builder.contentType(MediaType.APPLICATION_OCTET_STREAM); - filename = URLEncoder.encode(filename, "UTF-8"); - if (isIeBrowser) { - builder.header("Content-Disposition", "attachment; filename=" + filename); - } else { - builder.header("Content-Disposition", "attacher; filename*=UTF-8''" + filename); - } - } - return builder.body(FileUtils.readFileToByteArray(file)); + + // 调用文件存储工厂,读取文件,返回字节数组 + byte[] fileBytes = gaeaOSSTemplate.downloadFile(fileObjectName); + + // 根据文件后缀来判断,是显示图片\视频\音频,还是下载文件 + return ResponseUtil.writeBody(originalFilename, fileBytes, isIEBrowser); } catch (Exception e) { - log.error("file download error: {}", e); - return null; + log.error("file download error", e); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); + } + } + + /** + * 获取文件 + * + * @param fileId + * @return + */ + @Override + public byte[] getFile(String fileId) { + // fileId必填 + if(StringUtils.isBlank(fileId)){ + throw BusinessExceptionBuilder.build(ResponseCode.FILE_ONT_EXSIT); + } + // 根据fileId,从gaea_file中读出filePath + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(); + queryWrapper.eq(GaeaFile::getFileId, fileId); + GaeaFile gaeaFile = gaeaFileMapper.selectOne(queryWrapper); + if (null == gaeaFile) { + throw BusinessExceptionBuilder.build(ResponseCode.FILE_ONT_EXSIT); } + + // 在oss中存储的文件名 402b6193e70e40a9bf5b73a78ea1e8ab.png + String fileObjectName = gaeaFile.getFilePath(); + String originalFilename = gaeaFile.getFileInstruction(); + if (StringUtils.isBlank(fileObjectName) || StringUtils.isBlank(originalFilename)) { + throw BusinessExceptionBuilder.build(ResponseCode.FILE_ONT_EXSIT); + } + + // 调用文件存储工厂,读取文件,返回字节数组 + return gaeaOSSTemplate.downloadFile(fileObjectName); } /** @@ -212,10 +220,7 @@ public class GaeaFileServiceImpl implements GaeaFileService { // 删除本地文件 entities.forEach(gaeaFile -> { String filePath = gaeaFile.getFilePath(); - File file = new File(filePath); - if (file.exists()) { - file.delete(); - } + gaeaOSSTemplate.deleteFile(filePath); }); } diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/service/impl/ReportExcelServiceImpl.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/service/impl/ReportExcelServiceImpl.java index b25832d6..5af31651 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/service/impl/ReportExcelServiceImpl.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/service/impl/ReportExcelServiceImpl.java @@ -58,10 +58,10 @@ public class ReportExcelServiceImpl implements ReportExcelService { @Autowired private ReportMapper reportMapper; - @Value("${customer.file.dist-path:''}") + @Value("${customer.file.tmp-path:.}") private String dictPath; - @Value("${customer.file.downloadPath:''}") + @Value("${spring.gaea.subscribes.oss.downloadPath:''}") private String fileDownloadPath; @Autowired diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/util/FileUtil.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/util/FileUtil.java index 5532b53d..a0ac7365 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/util/FileUtil.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/util/FileUtil.java @@ -1,7 +1,7 @@ package com.anjiplus.template.gaea.business.util; -import com.anji.plus.gaea.code.ResponseCode; import com.anji.plus.gaea.exception.BusinessExceptionBuilder; +import com.anjiplus.template.gaea.business.code.ResponseCode; import lombok.extern.slf4j.Slf4j; import org.springframework.web.multipart.MultipartFile; @@ -42,7 +42,7 @@ public class FileUtil { log.info("链接下载图片:{},临时路径:{}", urlPath, path); } catch (IOException e) { log.error("根据链接下载失败", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } } @@ -66,14 +66,14 @@ public class FileUtil { outputChannel.transferFrom(inputChannel, 0, inputChannel.size()); } catch (IOException e) { log.error("复制文件失败", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } finally { try { inputChannel.close(); outputChannel.close(); } catch (IOException e) { log.error("", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } } } @@ -106,7 +106,7 @@ public class FileUtil { outputStream.close(); } catch (Exception e) { log.error("写入文件失败", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } } @@ -132,20 +132,20 @@ public class FileUtil { return sbf.toString(); } catch (IOException e) { log.error("读文件失败", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } finally { if (null != isr) { try { isr.close(); } catch (IOException e) { - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } } if (reader != null) { try { reader.close(); } catch (IOException e1) { - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e1.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e1.getMessage()); } } } @@ -185,14 +185,14 @@ public class FileUtil { compress(srcFile, zipOut, baseDir); } catch (IOException e) { log.error("压缩文件夹失败", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } finally { if (null != zipOut) { try { zipOut.close(); } catch (IOException e) { log.error("", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } out = null; } @@ -201,7 +201,7 @@ public class FileUtil { out.close(); } catch (IOException e) { log.error("", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } } } @@ -246,14 +246,14 @@ public class FileUtil { } catch (IOException e) { log.error("压缩文件夹失败", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } finally { if (null != bis) { try { bis.close(); } catch (IOException e) { log.error("", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } } } @@ -264,23 +264,26 @@ public class FileUtil { decompress(new ZipFile(zipFile), dstPath); } catch (IOException e) { log.error("", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } } public static void decompress(MultipartFile zipFile, String dstPath) { try { - File file = new File(dstPath + File.separator + zipFile.getOriginalFilename()); - if (!file.getParentFile().exists()) { - file.getParentFile().mkdirs(); + File dir = new File(dstPath); + if (!dir.exists()){ + dir.mkdirs(); } + String path = dir.getPath(); + String absolutePath = dir.getAbsolutePath(); + File file = new File(dir.getAbsolutePath() + File.separator + zipFile.getOriginalFilename()); zipFile.transferTo(file); decompress(new ZipFile(file), dstPath); //解压完删除 file.delete(); } catch (IOException e) { log.error("", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } } @@ -326,14 +329,14 @@ public class FileUtil { } } catch (IOException e) { log.error("解压失败", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } finally { if (null != in) { try { in.close(); } catch (IOException e) { log.error("", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } } @@ -342,7 +345,7 @@ public class FileUtil { out.close(); } catch (IOException e) { log.error("", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } } } @@ -350,7 +353,7 @@ public class FileUtil { zip.close(); } catch (IOException e) { log.error("解压失败", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } } @@ -371,7 +374,7 @@ public class FileUtil { ins.close(); } catch (Exception e) { log.error("获取流文件失败", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); } } @@ -399,8 +402,49 @@ public class FileUtil { }); } catch (IOException e) { log.error("删除文件失败", e); - throw BusinessExceptionBuilder.build(ResponseCode.FAIL_CODE, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); + } + } + + /** + * byte 转file + */ + public static File byte2File(byte[] buf, String filePath, String fileName){ + BufferedOutputStream bos = null; + FileOutputStream fos = null; + File file = null; + try{ + File dir = new File(filePath); + if (!dir.exists()){ + dir.mkdirs(); + } + file = new File(filePath + File.separator + fileName); + fos = new FileOutputStream(file); + bos = new BufferedOutputStream(fos); + bos.write(buf); + }catch (Exception e){ + log.error("", e); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); + } + finally{ + if (bos != null){ + try{ + bos.close(); + }catch (IOException e){ + log.error("", e); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); + } + } + if (fos != null){ + try{ + fos.close(); + }catch (IOException e){ + log.error("", e); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); + } + } } + return file; } diff --git a/report-core/src/main/resources/bootstrap-dev.yml b/report-core/src/main/resources/bootstrap-dev.yml index ad947c14..e11aeecb 100644 --- a/report-core/src/main/resources/bootstrap-dev.yml +++ b/report-core/src/main/resources/bootstrap-dev.yml @@ -4,8 +4,15 @@ spring: url: jdbc:mysql://10.108.26.197:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false username: root password: appuser@anji + gaea: + subscribes: + oss: #文件存储 + enabled: true + ##允许上传的文件后缀 + file-type-while-list: .png|.jpg|.gif|.icon|.pdf|.xlsx|.xls|.csv|.mp4|.avi|.jpeg + # 用于文件上传成功后,生成文件的下载公网完整URL + downloadPath: http://127.0.0.1:9095/file/download + nfs: + path: D:\\aaa\\ + -customer: - file: - dist-path: D:\Workspace\AJ-Report\report-core\upload - downloadPath: http://127.0.0.1:9095/file/download diff --git a/report-core/src/main/resources/bootstrap-prod.yml b/report-core/src/main/resources/bootstrap-prod.yml index 17071c3d..d2b38dd9 100644 --- a/report-core/src/main/resources/bootstrap-prod.yml +++ b/report-core/src/main/resources/bootstrap-prod.yml @@ -4,7 +4,3 @@ spring: url: jdbc:mysql://10.108.26.197:3306/aj_report?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false username: root password: appuser@anji - -customer: - file: - dist-path: /app/disk/upload/ \ No newline at end of file diff --git a/report-core/src/main/resources/bootstrap.yml b/report-core/src/main/resources/bootstrap.yml index 2d3581a3..3eb10d5b 100644 --- a/report-core/src/main/resources/bootstrap.yml +++ b/report-core/src/main/resources/bootstrap.yml @@ -46,6 +46,30 @@ spring: placeholder-replacement: false init-sqls: - CREATE DATABASE IF NOT EXISTS `aj_report` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; + gaea: + subscribes: + oss: #文件存储 + enabled: true + ##允许上传的文件后缀 + file-type-while-list: .png|.jpg|.gif|.icon|.pdf|.xlsx|.xls|.csv|.mp4|.avi|.jpeg|.aaa + # 用于文件上传成功后,生成文件的下载公网完整URL + downloadPath: http://10.108.26.197:9095/file/download + nfs: + path: /app/disk/upload/ + #若要使用minio文件存储,请启用以下配置 + #minio: + # url: http://127.0.0.1 + # port: 9000 + # access-key: minioreport + # secret-key: minioreport + # bucket-name: aj-report + #若要使用amazonS3文件存储,请启用以下配置 + #amazonS3: + # url: http://127.0.0.1 + # access-key: access-key + # secret-key: secret-key + # bucket-name: AJ-Report + #若minio和amazonS3都没有,使用服务器高可用的nfs共享盘 mybatis-plus: configuration: @@ -64,16 +88,6 @@ logging: # 本应用自定义参数 customer: - # 开发测试用本地文件,如果是生产,请考虑使用对象存储 - file: - #上传对应本地全路径,目录必须是真实存在的,注意 Win是 \ 且有盘符,linux是 / 无盘符 - dist-path: /app/disk/upload/ - #dist-path: D:\Download - white-list: .png|.jpg|.jpeg|.gif|.icon|.pdf|.xlsx|.xls|.csv|.mp4|.avi - excelSuffix: .xlsx|.xls|.csv - #上传对应下载的下载链接路径 http://serverip:9095/file/download - downloadPath: http://10.108.26.197:9095/file/download - # 跳过token验证和权限验证的url清单 skip-authenticate-urls: /gaeaDict/all, /login, /static, /file/download/, /index.html, /favicon.ico, /reportShare/detailByCode user: diff --git a/report-core/src/main/resources/i18n/messages_en_US.properties b/report-core/src/main/resources/i18n/messages_en_US.properties index 209a129b..9b373895 100644 --- a/report-core/src/main/resources/i18n/messages_en_US.properties +++ b/report-core/src/main/resources/i18n/messages_en_US.properties @@ -9,8 +9,9 @@ user.old.password.error=user old password error 1013=The code does not allow duplication 2001=File names are not allowed to be empty 2002=Unsupported suffix type -2003=File upload failed +2003=File upload failed:{0} 2004=File does not exist +file.operation.failed=File operation failed\uFF1A{0} field.not.null={} can not be null field.not.empty={} can not be empty diff --git a/report-core/src/main/resources/i18n/messages_zh_CN.properties b/report-core/src/main/resources/i18n/messages_zh_CN.properties index b9e90864..7222ba5c 100644 --- a/report-core/src/main/resources/i18n/messages_zh_CN.properties +++ b/report-core/src/main/resources/i18n/messages_zh_CN.properties @@ -8,8 +8,9 @@ user.old.password.error=\u65E7\u5BC6\u7801\u4E0D\u6B63\u786E 1013=\u7F16\u7801\u4E0D\u5141\u8BB8\u91CD\u590D 2001=\u6587\u4EF6\u540D\u4E0D\u5141\u8BB8\u4E3A\u7A7A 2002=\u6587\u4EF6\u7C7B\u578B\u4E0D\u652F\u6301 -2003=\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25 +2003=\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25\uFF1A{0} 2004=\u6587\u4EF6\u4E0D\u5B58\u5728 +file.operation.failed=\u6587\u4EF6\u64CD\u4F5C\u5931\u8D25\uFF1A{0} field.not.null={}\u4E0D\u80FD\u4E3Anull field.not.empty={}\u4E0D\u80FD\u4E3A\u7A7A\u5B57\u7B26\u4E32