From bd8e11a6630dbe35ed4eb66800e79a11997bcf57 Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Sat, 15 Nov 2025 15:22:30 +0800 Subject: [PATCH] =?UTF-8?q?cos=20=E4=B8=8A=E4=BC=A0=E9=92=88=E5=AF=B9?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E4=BF=9D=E7=9C=9F=E5=8E=8B=E7=BC=A9=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oss/service/impl/OssServiceImpl.java | 6 +- .../suisung/mall/common/utils/UploadUtil.java | 249 ++++++++++++++++++ .../lakala/service/impl/LklTkServiceImpl.java | 216 +++++++++------ .../page/service/impl/OssServiceImpl.java | 10 +- 4 files changed, 396 insertions(+), 85 deletions(-) diff --git a/mall-admin/src/main/java/com/suisung/mall/admin/oss/service/impl/OssServiceImpl.java b/mall-admin/src/main/java/com/suisung/mall/admin/oss/service/impl/OssServiceImpl.java index 0867d7a4..2a9078ad 100644 --- a/mall-admin/src/main/java/com/suisung/mall/admin/oss/service/impl/OssServiceImpl.java +++ b/mall-admin/src/main/java/com/suisung/mall/admin/oss/service/impl/OssServiceImpl.java @@ -30,6 +30,7 @@ import com.suisung.mall.common.pojo.dto.OssCallbackResultDTO; import com.suisung.mall.common.pojo.dto.OssPolicyResultDTO; import com.suisung.mall.common.utils.I18nUtil; import com.suisung.mall.common.utils.LogUtil; +import com.suisung.mall.common.utils.UploadUtil; import com.suisung.mall.common.utils.VideoUtil; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; @@ -169,6 +170,9 @@ public class OssServiceImpl implements OssService { * @return */ public Map upload(MultipartFile file, UserDto user, String dir, String uploadPath, String uploadName, String fileName) { + // 如果是图片,先压缩图片,再上传到 cos 对象存储 + file = UploadUtil.compressImageIfNeeded(file, 2048); + // 创建临时文件 creTempFile(file, dir, uploadName); String url = null; @@ -248,7 +252,7 @@ public class OssServiceImpl implements OssService { tempFile.delete(); logger.info("临时文件已删除: {}", uploadPath); } - + // 同时删除可能创建的封面文件 String coverPath = uploadPath.replace("." + VideoUtil.getVideoFormat(uploadPath), ".jpg"); File coverFile = new File(coverPath); diff --git a/mall-common/src/main/java/com/suisung/mall/common/utils/UploadUtil.java b/mall-common/src/main/java/com/suisung/mall/common/utils/UploadUtil.java index 5673d391..15693f67 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/utils/UploadUtil.java +++ b/mall-common/src/main/java/com/suisung/mall/common/utils/UploadUtil.java @@ -6,8 +6,11 @@ import org.apache.tika.Tika; import org.springframework.util.Base64Utils; import org.springframework.web.multipart.MultipartFile; +import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.awt.*; +import java.awt.image.BufferedImage; import java.io.*; import java.net.*; import java.nio.file.Files; @@ -437,4 +440,250 @@ public class UploadUtil { } + /** + * 压缩图片文件以提高质量。 + * 如果文件大小超过500KB,则在保持宽高比的同时调整大小 + * 以提高清晰度并减小文件大小。 + * + * @param file 原始图片文件 + * @param pixelLimit 像素限制 + * @return 压缩后的图片文件,如果不需要压缩则返回原始文件 + */ + public static MultipartFile compressImageIfNeeded(MultipartFile file, Integer pixelLimit) { + if (file == null) { + return null; + } + + try { + // 检查文件是否为图片格式 + String contentType = file.getContentType(); + if (contentType == null || !contentType.startsWith("image/")) { + log.debug("文件不是图片格式,跳过压缩: {}", contentType); + return file; + } + + if (pixelLimit == null) { + pixelLimit = 2048; + } + + // 小文件直接返回 + if (file.getSize() <= 512000) { // 500KB + log.debug("文件大小在限制范围内 ({} 字节),无需压缩", file.getSize()); + return file; + } + + // 将MultipartFile转换为BufferedImage + BufferedImage originalImage = ImageIO.read(file.getInputStream()); + if (originalImage == null) { + log.warn("读取图片文件失败,跳过压缩"); + return file; + } + + int originalWidth = originalImage.getWidth(); + int originalHeight = originalImage.getHeight(); + + // 小图片直接返回 + if (originalWidth <= pixelLimit && originalHeight <= pixelLimit) { + log.debug("图片尺寸在限制范围内 ({}x{}),无需调整大小", originalWidth, originalHeight); + return file; + } + + // 计算保持宽高比的新尺寸 + double aspectRatio = (double) originalWidth / originalHeight; + int newWidth, newHeight; + + // 目标尺寸:最长边最大为pixelLimit像素 + if (originalWidth > originalHeight) { + newWidth = Math.min(pixelLimit, originalWidth); + newHeight = (int) (newWidth / aspectRatio); + } else { + newHeight = Math.min(pixelLimit, originalHeight); + newWidth = (int) (newHeight * aspectRatio); + } + + // 确保最小尺寸 + newWidth = Math.max(newWidth, 1); + newHeight = Math.max(newHeight, 1); + + log.debug("调整图片尺寸从 {}x{} 到 {}x{}", originalWidth, originalHeight, newWidth, newHeight); + + // 获取图片格式并执行高质量渐进式缩放 + String format = getImageFormat(file.getOriginalFilename()); + BufferedImage resizedImage = progressiveResize(originalImage, newWidth, newHeight, format); + + // 转换回MultipartFile + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageIO.write(resizedImage, format, baos); + byte[] compressedBytes = baos.toByteArray(); + + log.info("图片从 {} 字节压缩到 {} 字节", file.getSize(), compressedBytes.length); + + return new InMemoryMultipartFile( + file.getName(), + file.getOriginalFilename(), + file.getContentType(), + compressedBytes + ); + + } catch (Exception e) { + log.error("压缩图片时出错,使用原始文件: {}", e.getMessage(), e); + return file; + } + } + + /** + * 渐进式调整图片大小以提高质量 + * + * @param originalImage 原始图片 + * @param targetWidth 目标宽度 + * @param targetHeight 目标高度 + * @param format 图片格式 + * @return 调整大小后的图片,质量更好 + */ + private static BufferedImage progressiveResize(BufferedImage originalImage, int targetWidth, int targetHeight, String format) { + int currentWidth = originalImage.getWidth(); + int currentHeight = originalImage.getHeight(); + + // 多步缩小以提高质量 + BufferedImage resizedImage = originalImage; + + while (currentWidth > targetWidth * 2 || currentHeight > targetHeight * 2) { + currentWidth = Math.max(targetWidth, currentWidth / 2); + currentHeight = Math.max(targetHeight, currentHeight / 2); + + resizedImage = scaleImage(resizedImage, currentWidth, currentHeight, format); + } + + // 最终调整到目标尺寸 + return scaleImage(resizedImage, targetWidth, targetHeight, format); + } + + /** + * 使用高质量渲染提示缩放图片 + * + * @param originalImage 原始图片 + * @param targetWidth 目标宽度 + * @param targetHeight 目标高度 + * @param format 图片格式 + * @return 缩放后的图片 + */ + private static BufferedImage scaleImage(BufferedImage originalImage, int targetWidth, int targetHeight, String format) { + int imageType = getImageTypeForFormat(format); + BufferedImage scaledImage = new BufferedImage(targetWidth, targetHeight, imageType); + Graphics2D g2d = scaledImage.createGraphics(); + + // 高质量渲染设置 + g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); + g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); + g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); + g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + + g2d.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null); + g2d.dispose(); + + return scaledImage; + } + + /** + * 根据文件扩展名获取图片格式,支持更多格式 + * + * @param filename 原始文件名 + * @return 图片格式 (jpg, png, gif 等) + */ + private static String getImageFormat(String filename) { + if (StrUtil.isBlank(filename)) { + return "jpg"; + } + + String extension = filename.substring(filename.lastIndexOf('.') + 1).toLowerCase(); + switch (extension) { + case "png": + return "png"; + case "gif": + return "gif"; + case "bmp": + return "bmp"; + case "wbmp": + return "wbmp"; + case "jpeg": + case "jpg": + return "jpeg"; + default: + return "jpeg"; + } + } + + /** + * 根据格式确定适当的图片类型以保留透明度 + * + * @param format 图片格式 + * @return BufferedImage类型 + */ + private static int getImageTypeForFormat(String format) { + if ("png".equalsIgnoreCase(format) || "gif".equalsIgnoreCase(format)) { + return BufferedImage.TYPE_INT_ARGB; // 保留透明度 + } + return BufferedImage.TYPE_INT_RGB; // JPEG等格式的默认值 + } + + + /** + * Simple MultipartFile implementation for in-memory data + */ + private static class InMemoryMultipartFile implements MultipartFile { + private final String name; + private final String originalFilename; + private final String contentType; + private final byte[] content; + + public InMemoryMultipartFile(String name, String originalFilename, String contentType, byte[] content) { + this.name = name; + this.originalFilename = originalFilename; + this.contentType = contentType; + this.content = content; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getOriginalFilename() { + return originalFilename; + } + + @Override + public String getContentType() { + return contentType; + } + + @Override + public boolean isEmpty() { + return content == null || content.length == 0; + } + + @Override + public long getSize() { + return content.length; + } + + @Override + public byte[] getBytes() throws IOException { + return content; + } + + @Override + public InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(content); + } + + @Override + public void transferTo(File dest) throws IOException, IllegalStateException { + new FileOutputStream(dest).write(content); + } + } } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklTkServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklTkServiceImpl.java index c9a6337a..c934f2d2 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklTkServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklTkServiceImpl.java @@ -136,85 +136,124 @@ public class LklTkServiceImpl { * 身份证反面:ID_CARD_BEHIND; * 营业执照:BUSINESS_LICENCE; * 银行卡:BANK_CARD - * @return + * @return 上传结果及OCR识别信息 */ public CommonResult uploadOcrImg(MultipartFile file, String imgType) { - UserDto currentUser = getCurrentUser(); - if (currentUser == null) { - currentUser = new UserDto(); - } - + // 参数校验 if (file == null || StrUtil.isBlank(imgType)) { + logger.warn("上传文件参数缺失: imgType={}", imgType); return CommonResult.failed("上传文件或图片类型不能为空"); } - CommonResult ossImgInfo = ossService.uploadFile(file, currentUser); - if (ossImgInfo == null) { - return CommonResult.failed("上传文件失败"); - } - - if (ossImgInfo.getStatus() != ResultCode.SUCCESS.getStatus() || ossImgInfo.getData() == null) { - return CommonResult.failed(ossImgInfo.getMsg()); - } - - String imgURL = JSONUtil.parseObj(ossImgInfo.getData()).getStr("url"); - - String authorization = getLklTkAuthorization(); - if (StrUtil.isBlank(authorization)) { - return CommonResult.failed("获取拉卡拉token失败"); - } - - JSONObject header = new JSONObject(); - header.put("Authorization", authorization); - - - String fileBase64 = UploadUtil.multipartFileToBase64(file); - if (StrUtil.isBlank(fileBase64)) { - return CommonResult.failed("解析文件转换失败"); - } - // Base64Utils.encodeToString(file.getBytes()); - - JSONObject requestBody = new JSONObject(); - requestBody.put("fileBase64", fileBase64); - requestBody.put("imgType", imgType); - requestBody.put("sourcechnl", "0"); // 来源: 0:PC,1:安卓,2:IOS - requestBody.put("isOcr", "true"); - - String urlPath = "/sit/htkregistration/file/base/upload"; - if (isLklProd) { - // 生产环境启用 - urlPath = "/registration/file/base/upload"; - } - try { - ResponseEntity updResponse = RestTemplateHttpUtil.sendPostBodyBackEntity(buildLklTkUrl(urlPath), header, requestBody, JSONObject.class); - if (ObjectUtil.isEmpty(updResponse) - || updResponse.getStatusCode() != HttpStatus.OK - || ObjectUtil.isEmpty(updResponse.getBody())) { + UserDto currentUser = getCurrentUser(); + if (currentUser == null) { + currentUser = new UserDto(); + } + + // Compress image if needed before processing + MultipartFile processedFile = UploadUtil.compressImageIfNeeded(file, 2048); + if (processedFile == null) { + logger.warn("上传文件压缩失败: filename={}, imgType={}", + file.getOriginalFilename(), imgType); + return CommonResult.failed("服务繁忙,请重试!"); + } + + // 上传文件到OSS + CommonResult ossImgInfo = ossService.uploadFile(processedFile, currentUser); + if (ossImgInfo == null) { + logger.error("上传文件到OSS失败,filename={}, imgType={}", + processedFile.getOriginalFilename(), imgType); + return CommonResult.failed("上传文件失败"); + } + + if (ossImgInfo.getStatus() != ResultCode.SUCCESS.getStatus() || ossImgInfo.getData() == null) { + logger.error("OSS上传响应异常,filename={}, imgType={}, status={}", + processedFile.getOriginalFilename(), imgType, ossImgInfo.getStatus()); + return CommonResult.failed(ossImgInfo.getMsg()); + } + + String imgURL = JSONUtil.parseObj(ossImgInfo.getData()).getStr("url"); + logger.debug("文件上传OSS成功,filename={}", processedFile.getOriginalFilename()); + + // 获取拉卡拉认证信息 + String authorization = getLklTkAuthorization(); + if (StrUtil.isBlank(authorization)) { + logger.error("获取拉卡拉token失败,filename={}, imgType={}", + processedFile.getOriginalFilename(), imgType); + return CommonResult.failed("获取拉卡拉token失败"); + } + + // 构造请求头 + JSONObject header = new JSONObject(); + header.put("Authorization", authorization); + + // 文件转Base64 + String fileBase64 = UploadUtil.multipartFileToBase64(processedFile); + if (StrUtil.isBlank(fileBase64)) { + logger.error("文件转换Base64失败,filename={}, imgType={}", + processedFile.getOriginalFilename(), imgType); + return CommonResult.failed("解析文件转换失败"); + } + + // 构造请求体 + JSONObject requestBody = new JSONObject(); + requestBody.put("fileBase64", fileBase64); + requestBody.put("imgType", imgType); + requestBody.put("sourcechnl", "0"); // 来源: 0:PC,1:安卓,2:IOS + requestBody.put("isOcr", "true"); + + // 构造请求路径 + String urlPath = "/sit/htkregistration/file/base/upload"; + if (isLklProd) { + urlPath = "/registration/file/base/upload"; + } + + // 发送请求并获取响应 + ResponseEntity updResponse = RestTemplateHttpUtil.sendPostBodyBackEntity( + buildLklTkUrl(urlPath), header, requestBody, JSONObject.class); + + logger.info("调用拉卡拉文件上传接口,filename={}, imgType={}", + processedFile.getOriginalFilename(), imgType); + + // 检查响应有效性 + if (ObjectUtil.isEmpty(updResponse) || + updResponse.getStatusCode() != HttpStatus.OK || + ObjectUtil.isEmpty(updResponse.getBody())) { + logger.error("拉卡拉文件上传响应数据异常,filename={}, imgType={}", + processedFile.getOriginalFilename(), imgType); return CommonResult.failed("上传文件返回值有误"); } - // {batchNo,status,url,showUrl,result{} } + // 提取上传结果 JSONObject updObj = updResponse.getBody(); String batchNo = updObj.getStr("batchNo"); if (StrUtil.isBlank(batchNo)) { + logger.error("拉卡拉文件上传返回批次号为空,filename={}, imgType={}", + processedFile.getOriginalFilename(), imgType); return CommonResult.failed("上传文件返回值有误"); } updObj.put("cosURL", imgURL); + logger.info("拉卡拉文件上传成功,filename={}, imgType={}, batchNo={}", + processedFile.getOriginalFilename(), imgType, batchNo); return CommonResult.success(updObj); + } catch (Exception e) { - logger.error("上传文件失败: ", e.getMessage()); + logger.error("上传文件过程发生异常,filename={}, imgType={}", + file != null ? file.getOriginalFilename() : "unknown", imgType, e); return CommonResult.failed("上传文件失败:" + e.getMessage()); } } + /** * 根据上传的图片的批次号,获取 OCR 识别结果 * - * @param batchNo - * @param imgType * ID_CARD_FRONT 身份证正⾯ + * @param batchNo 批次号 + * @param imgType 图片类型 + * * ID_CARD_FRONT 身份证正⾯ * * ID_CARD_BEHIND 身份证反⾯ * * BUSINESS_LICENCE 营业执照照⽚ * * BANK_CARD 银行卡(企业对公不需要传) @@ -227,55 +266,70 @@ public class LklTkServiceImpl { * * SETTLE_ID_CARD_FRONT 结算人身份证人像面 * * SETTLE_ID_CARD_BEHIND 结算人身份证国徽面 * * LETTER_OF_AUTHORIZATION 法人授权涵 - * @return + * @return OCR识别结果 */ public CommonResult imgOcrResult(String batchNo, String imgType) { + // 参数校验 if (StrUtil.isBlank(batchNo) || StrUtil.isBlank(imgType)) { + logger.warn("OCR识别参数缺失: batchNo={}, imgType={}", batchNo, imgType); return CommonResult.failed("批次号或图片类型不能为空"); } - // 调用 OCR 识别接口 - String authorization = getLklTkAuthorization(); - if (StrUtil.isBlank(authorization)) { - return CommonResult.failed("获取拉卡拉token失败"); - } - - JSONObject header = new JSONObject(); - header.put("Authorization", authorization); - - - JSONObject ocrRequestBody = new JSONObject(); - ocrRequestBody.put("batchNo", batchNo); - ocrRequestBody.put("imgType", imgType); - logger.info("ocr请求参数:{}", ocrRequestBody); - - String urlPath = "/sit/htkregistration/ocr/result"; - if (isLklProd) { - // 生产环境启用 - urlPath = "/registration/ocr/result"; - } - try { - ResponseEntity ocrResponse = RestTemplateHttpUtil.sendPostBodyBackEntity(buildLklTkUrl(urlPath), header, ocrRequestBody, JSONObject.class); - if (ObjectUtil.isEmpty(ocrResponse) - || ocrResponse.getStatusCode() != HttpStatus.OK - || ObjectUtil.isEmpty(ocrResponse.getBody())) { + // 获取认证信息 + String authorization = getLklTkAuthorization(); + if (StrUtil.isBlank(authorization)) { + logger.error("获取拉卡拉token失败,batchNo={}, imgType={}", batchNo, imgType); + return CommonResult.failed("获取拉卡拉token失败"); + } + + // 构造请求头 + JSONObject header = new JSONObject(); + header.put("Authorization", authorization); + + // 构造请求体 + JSONObject ocrRequestBody = new JSONObject(); + ocrRequestBody.put("batchNo", batchNo); + ocrRequestBody.put("imgType", imgType); + logger.info("调用OCR识别接口,batchNo={}, imgType={}", batchNo, imgType); + + // 构造请求路径 + String urlPath = "/sit/htkregistration/ocr/result"; + if (isLklProd) { + urlPath = "/registration/ocr/result"; + } + + // 发送请求并获取响应 + ResponseEntity ocrResponse = RestTemplateHttpUtil.sendPostBodyBackEntity( + buildLklTkUrl(urlPath), header, ocrRequestBody, JSONObject.class); + + // 检查响应有效性 + if (ObjectUtil.isEmpty(ocrResponse) || + ocrResponse.getStatusCode() != HttpStatus.OK || + ObjectUtil.isEmpty(ocrResponse.getBody())) { + logger.error("OCR识别响应数据异常,batchNo={}, imgType={}", batchNo, imgType); return CommonResult.failed("OCR响应数据有误"); } - JSONObject ocrObj = ocrResponse.getBody().get("result", JSONObject.class); - logger.info("ocr返回结果:{}", ocrResponse); + // 提取OCR结果 + JSONObject result = ocrResponse.getBody(); + JSONObject ocrObj = result.get("result", JSONObject.class); + logger.info("OCR识别成功,batchNo={}, imgType={}", batchNo, imgType); + if (ObjectUtil.isEmpty(ocrObj)) { + logger.warn("OCR识别返回结果为空,batchNo={}, imgType={}", batchNo, imgType); return CommonResult.failed("OCR返回结果有误"); } return CommonResult.success(ocrObj); + } catch (Exception e) { - logger.error("OCR识别失败: ", e.getMessage()); + logger.error("OCR识别过程发生异常,batchNo={}, imgType={}", batchNo, imgType, e); return CommonResult.failed("OCR识别失败:" + e.getMessage()); } } + /** * (商户进件前)请求获取token * diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/OssServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/OssServiceImpl.java index c689ae78..dbba7329 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/OssServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/OssServiceImpl.java @@ -27,6 +27,7 @@ import com.suisung.mall.common.pojo.dto.OssPolicyResultDTO; import com.suisung.mall.common.utils.CheckUtil; import com.suisung.mall.common.utils.I18nUtil; import com.suisung.mall.common.utils.LogUtil; +import com.suisung.mall.common.utils.UploadUtil; import com.suisung.mall.shop.base.service.AccountBaseConfigService; import com.suisung.mall.shop.page.service.OssService; import com.suisung.mall.shop.page.utis.VideoUtil; @@ -144,7 +145,7 @@ public class OssServiceImpl implements OssService { throw new ApiException(String.format(I18nUtil._("允许上传格式为:【%s】"), StringUtils.join(allowExtList, ","))); } - Map result = upload(file, user, dir, uploadPath, uploadName, fileName); + Map result = upload(file, user, dir, uploadPath, uploadName); String url = (String) result.get("media_url"); String thumb = (String) result.get("thumb"); @@ -173,7 +174,10 @@ public class OssServiceImpl implements OssService { * @param user 用户信息 * @return */ - public Map upload(MultipartFile file, UserDto user, String dir, String uploadPath, String uploadName, String fileName) { + public Map upload(MultipartFile file, UserDto user, String dir, String uploadPath, String uploadName) { + // 如果是图片,先压缩图片,再上传到 cos 对象存储 + file = UploadUtil.compressImageIfNeeded(file, 2048); + // 创建临时文件 creTempFile(file, dir, uploadName); // String localUrl = IP + "/admin/shop/static/image/" + dir + uploadName; // 文件本地路径 @@ -294,7 +298,7 @@ public class OssServiceImpl implements OssService { throw new ApiException(String.format(I18nUtil._("允许上传格式为:【%s】"), StringUtils.join(allowExtList, ","))); } - return upload(file, user, dir, uploadPath, uploadName, fileName); + return upload(file, user, dir, uploadPath, uploadName); } /**