| | |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.yami.trading.common.exception.BusinessException; |
| | | import com.yami.trading.common.exception.YamiShopBindException; |
| | | import com.yami.trading.common.util.PropertiesUtil; |
| | | import com.yami.trading.service.AwsS3OSSFileService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import net.coobird.thumbnailator.Thumbnails; |
| | |
| | | @Service |
| | | @Slf4j |
| | | public class AwsS3OSSFileServiceImpl implements AwsS3OSSFileService { |
| | | |
| | | @Value("${oss.aws.s3.bucketName}") |
| | | private String bucketName; |
| | | // |
| | |
| | | @Override |
| | | public String uploadFile(String moduleName, MultipartFile file) { |
| | | // 兼容c端组件上传原理 |
| | | String fileType = file.getOriginalFilename(); |
| | | String originalFilename = file.getOriginalFilename(); |
| | | String fileType = originalFilename != null ? originalFilename : ""; |
| | | if (StrUtil.isEmpty(fileType) || fileType.contains("blob")) { |
| | | fileType = "blob.png"; |
| | | } |
| | | |
| | | // 提取文件扩展名 |
| | | String extension = ""; |
| | | int dotIndex = fileType.lastIndexOf('.'); |
| | | if (dotIndex > 0) { |
| | | extension = fileType.substring(dotIndex); |
| | | } |
| | | |
| | | // 生成唯一的文件名 |
| | | String id = UUID.randomUUID().toString(); |
| | | String path = moduleName + "/" + LocalDate.now() + "/" + id + fileType; |
| | | log.info("AwsS3OSSFileService putS3Object bucketName:{},objectKey:{},objectPath:{}", bucketName, path, file.getName()); |
| | | String filename = id + extension; |
| | | String path = filename; // 直接使用文件名作为路径 |
| | | |
| | | // 确保目标文件夹存在 |
| | | File targetDir = new File(PropertiesUtil.getProperty("loca.images.dir")); |
| | | if (!targetDir.exists()) { |
| | | targetDir.mkdirs(); |
| | | // 设置目录权限为755 (rwxr-xr-x) |
| | | setFilePermissions(targetDir, "755"); |
| | | } |
| | | |
| | | // 构建本地文件路径 |
| | | File localFile = new File(targetDir, filename); |
| | | |
| | | // 打印上传路径 |
| | | log.info("LocalFileUploadService uploadFile localFilePath: {}", localFile.getAbsolutePath()); |
| | | |
| | | try { |
| | | // 将文件保存到本地 |
| | | file.transferTo(localFile); |
| | | |
| | | // 设置文件权限为644 (rw-r--r--) |
| | | setFilePermissions(localFile, "644"); |
| | | |
| | | // 如果需要自定义元数据,可以在此处理 |
| | | Map<String, String> metadata = new HashMap<>(); |
| | | metadata.put("x-amz-meta-myVal", "test"); |
| | | PutObjectRequest putOb = PutObjectRequest.builder() |
| | | .bucket(bucketName) |
| | | .key(path) |
| | | .metadata(metadata) |
| | | .build(); |
| | | S3Client s3Client = getS3Client(); |
| | | s3Client.putObject(putOb, RequestBody.fromInputStream(file.getInputStream(), file.getSize())); |
| | | |
| | | // 返回文件名 |
| | | return path; |
| | | } catch (S3Exception e) { |
| | | log.error("AwsS3OSSFileService putS3Object S3Exception", e.getMessage(), e.awsErrorDetails().errorMessage(), e); |
| | | throw new YamiShopBindException("文件上传失败"); |
| | | |
| | | } catch (IOException e) { |
| | | log.error("AwsS3OSSFileService putS3Object IOException", e.getMessage(), e); |
| | | log.error("LocalFileUploadService uploadFile IOException", e.getMessage(), e); |
| | | throw new YamiShopBindException("文件上传失败"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 设置文件或目录权限(使用数字格式) |
| | | * @param file 文件或目录对象 |
| | | * @param permissions 权限数字字符串,如 "644", "755" |
| | | */ |
| | | private void setFilePermissions(File file, String permissions) { |
| | | try { |
| | | // 使用数字格式的chmod命令(更可靠) |
| | | Process process = Runtime.getRuntime().exec(new String[]{"chmod", permissions, file.getAbsolutePath()}); |
| | | int exitCode = process.waitFor(); |
| | | |
| | | // 读取命令输出和错误信息 |
| | | String output = readProcessOutput(process.getInputStream()); |
| | | String error = readProcessOutput(process.getErrorStream()); |
| | | |
| | | if (exitCode != 0) { |
| | | log.warn("设置文件权限失败,文件: {}, 退出码: {}, 错误: {}", |
| | | file.getAbsolutePath(), exitCode, error); |
| | | } else { |
| | | log.debug("成功设置文件权限 {}: {}", permissions, file.getAbsolutePath()); |
| | | if (!output.isEmpty()) { |
| | | log.debug("命令输出: {}", output); |
| | | } |
| | | } |
| | | } catch (IOException | InterruptedException e) { |
| | | log.warn("设置文件权限时发生异常,文件: {}", file.getAbsolutePath(), e); |
| | | if (e instanceof InterruptedException) { |
| | | Thread.currentThread().interrupt(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 读取进程输出流 |
| | | */ |
| | | private String readProcessOutput(InputStream inputStream) throws IOException { |
| | | try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { |
| | | StringBuilder output = new StringBuilder(); |
| | | String line; |
| | | while ((line = reader.readLine()) != null) { |
| | | if (output.length() > 0) { |
| | | output.append("; "); |
| | | } |
| | | output.append(line); |
| | | } |
| | | return output.toString(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 验证文件权限(调试用) |
| | | */ |
| | | private void verifyFilePermissions(File file) { |
| | | try { |
| | | Process process = Runtime.getRuntime().exec(new String[]{"ls", "-l", file.getAbsolutePath()}); |
| | | process.waitFor(); |
| | | String output = readProcessOutput(process.getInputStream()); |
| | | log.info("文件权限验证: {}", output); |
| | | } catch (Exception e) { |
| | | log.warn("无法验证文件权限: {}", e.getMessage()); |
| | | } |
| | | } |
| | | // /** |
| | |
| | | String fileType = FilenameUtils.getExtension(fileName); |
| | | return imgTypes.contains(fileType.toLowerCase()); |
| | | } |
| | | |
| | | /** |
| | | * 上传图标 |
| | | * @param moduleName |
| | | * @param file |
| | | * @return |
| | | */ |
| | | @Override |
| | | public String uploadIcon(String moduleName, MultipartFile file) { |
| | | // 兼容c端组件上传原理 |
| | | String originalFilename = file.getOriginalFilename(); |
| | | String fileType = originalFilename != null ? originalFilename : ""; |
| | | if (StrUtil.isEmpty(fileType) || fileType.contains("blob")) { |
| | | fileType = "blob.png"; |
| | | } |
| | | |
| | | // 提取文件扩展名 |
| | | String extension = ""; |
| | | int dotIndex = fileType.lastIndexOf('.'); |
| | | if (dotIndex > 0) { |
| | | extension = fileType.substring(dotIndex); |
| | | } |
| | | |
| | | String filename = moduleName + extension; |
| | | String path = filename; // 直接使用文件名作为路径 |
| | | |
| | | // 确保目标文件夹存在 |
| | | File targetDir = new File(PropertiesUtil.getProperty("loca.images.dir") + "/symbol"); |
| | | if (!targetDir.exists()) { |
| | | targetDir.mkdirs(); |
| | | // 设置目录权限为755 (rwxr-xr-x) |
| | | setFilePermissions(targetDir, "755"); |
| | | } |
| | | |
| | | // 构建本地文件路径 |
| | | File localFile = new File(targetDir, filename); |
| | | |
| | | // 打印上传路径 |
| | | log.info("LocalFileUploadService uploadFile localFilePath: {}", localFile.getAbsolutePath()); |
| | | |
| | | try { |
| | | // 将文件保存到本地 |
| | | file.transferTo(localFile); |
| | | |
| | | // 设置文件权限为644 (rw-r--r--) |
| | | setFilePermissions(localFile, "644"); |
| | | |
| | | // 如果需要自定义元数据,可以在此处理 |
| | | Map<String, String> metadata = new HashMap<>(); |
| | | metadata.put("x-amz-meta-myVal", "test"); |
| | | |
| | | // 返回文件名 |
| | | return "symbol/" + path; |
| | | |
| | | } catch (IOException e) { |
| | | log.error("LocalFileUploadService uploadFile IOException", e.getMessage(), e); |
| | | throw new YamiShopBindException("文件上传失败"); |
| | | } |
| | | } |
| | | } |