客户照片上传功能
This commit is contained in:
@@ -4,18 +4,22 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.rj.common.AudioManagementConstants;
|
import com.rj.common.AudioManagementConstants;
|
||||||
import com.rj.common.DataEnrichmentUtil;
|
import com.rj.common.DataEnrichmentUtil;
|
||||||
|
import com.rj.dto.CustomerPhotoPreviewResult;
|
||||||
|
import com.rj.dto.CustomerPhotoUploadResult;
|
||||||
import com.rj.entity.AudioManagement;
|
import com.rj.entity.AudioManagement;
|
||||||
import com.rj.entity.CustomerManagement;
|
import com.rj.entity.CustomerManagement;
|
||||||
import com.rj.entity.SalesManagement;
|
import com.rj.entity.SalesManagement;
|
||||||
import com.rj.service.IAudioManagementService;
|
import com.rj.service.IAudioManagementService;
|
||||||
import com.rj.service.ICustomerManagementService;
|
import com.rj.service.ICustomerManagementService;
|
||||||
import com.rj.service.ISalesManagementService;
|
import com.rj.service.ISalesManagementService;
|
||||||
import com.rj.service.MinIOService;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.core.io.InputStreamResource;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@@ -35,7 +39,6 @@ import java.util.UUID;
|
|||||||
* @author 李中华 ,spllzh
|
* @author 李中华 ,spllzh
|
||||||
* @since 2025-08-07
|
* @since 2025-08-07
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/customerManagement")
|
@RequestMapping("/api/customerManagement")
|
||||||
@Tag(name = "客户管理", description = "客户管理相关接口")
|
@Tag(name = "客户管理", description = "客户管理相关接口")
|
||||||
@@ -50,9 +53,6 @@ public class CustomerManagementController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ISalesManagementService salesManagementService;
|
private ISalesManagementService salesManagementService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private MinIOService minIOService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增客户
|
* 新增客户
|
||||||
*/
|
*/
|
||||||
@@ -395,46 +395,46 @@ public class CustomerManagementController {
|
|||||||
@PostMapping("/uploadPhoto")
|
@PostMapping("/uploadPhoto")
|
||||||
@Operation(summary = "上传客户照片", description = "根据客户ID上传照片到 MinIO,返回文件访问 URL")
|
@Operation(summary = "上传客户照片", description = "根据客户ID上传照片到 MinIO,返回文件访问 URL")
|
||||||
public ResponseEntity<Map<String, Object>> uploadCustomerPhoto(
|
public ResponseEntity<Map<String, Object>> uploadCustomerPhoto(
|
||||||
@Parameter(description = "客户ID", required = true)
|
@Parameter(description = "客户ID")
|
||||||
@RequestParam String id,
|
@RequestParam String id,
|
||||||
@Parameter(description = "照片文件", required = true)
|
@Parameter(description = "照片文件", required = true)
|
||||||
@RequestParam("file") MultipartFile file) {
|
@RequestParam("file") MultipartFile file) {
|
||||||
|
CustomerPhotoUploadResult uploadResult = customerManagementService.uploadCustomerPhoto(id, file);
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
try {
|
result.put("success", uploadResult.isSuccess());
|
||||||
if (id == null || id.trim().isEmpty()) {
|
result.put("message", uploadResult.getMessage());
|
||||||
result.put("success", false);
|
if (uploadResult.getUrl() != null) {
|
||||||
result.put("message", "客户ID不能为空");
|
result.put("url", uploadResult.getUrl());
|
||||||
return ResponseEntity.badRequest().body(result);
|
|
||||||
}
|
|
||||||
if (file == null || file.isEmpty()) {
|
|
||||||
result.put("success", false);
|
|
||||||
result.put("message", "请选择要上传的文件");
|
|
||||||
return ResponseEntity.badRequest().body(result);
|
|
||||||
}
|
|
||||||
CustomerManagement customer = customerManagementService.getById(id.trim());
|
|
||||||
if (customer == null) {
|
|
||||||
result.put("success", false);
|
|
||||||
result.put("message", "客户不存在");
|
|
||||||
return ResponseEntity.badRequest().body(result);
|
|
||||||
}
|
|
||||||
String original = file.getOriginalFilename();
|
|
||||||
String ext = "";
|
|
||||||
if (original != null && original.contains(".")) {
|
|
||||||
ext = original.substring(original.lastIndexOf("."));
|
|
||||||
}
|
|
||||||
String objectName = "customer-management/photo/" + id.trim() + "/" + UUID.randomUUID().toString().replace("-", "") + ext;
|
|
||||||
String url = minIOService.uploadFileWithName(file, objectName);
|
|
||||||
log.info("客户照片已上传 MinIO,customerId={}, url={}", id, url);
|
|
||||||
result.put("success", true);
|
|
||||||
result.put("message", "上传成功");
|
|
||||||
result.put("url", url);
|
|
||||||
return ResponseEntity.ok(result);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("客户照片上传失败: {}", e.getMessage(), e);
|
|
||||||
result.put("success", false);
|
|
||||||
result.put("message", "上传失败:" + e.getMessage());
|
|
||||||
return ResponseEntity.internalServerError().body(result);
|
|
||||||
}
|
}
|
||||||
|
return ResponseEntity.status(uploadResult.getHttpStatus()).body(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户照片预览:从 MinIO 拉流返回图片。
|
||||||
|
* 方式一:传 {@code url}(与上传接口返回的 MinIO 访问 URL 一致)。
|
||||||
|
* 方式二:传 {@code id} + {@code photoType}(front / side / life),读取客户表中对应照片 URL。
|
||||||
|
*/
|
||||||
|
@GetMapping("/previewPhoto")
|
||||||
|
@Operation(summary = "预览客户照片", description = "根据 MinIO URL 或客户ID+照片类型从 MinIO 读取并返回图片流,便于 img 标签 src 引用")
|
||||||
|
public ResponseEntity<Resource> previewCustomerPhoto(
|
||||||
|
@Parameter(description = "MinIO 完整访问 URL(与 uploadPhoto 返回的 url 一致)")
|
||||||
|
@RequestParam(required = false) String url,
|
||||||
|
@Parameter(description = "客户ID,与 photoType 联用")
|
||||||
|
@RequestParam(required = false) String id,
|
||||||
|
@Parameter(description = "照片类型:front 正面 / side 侧面 / life 生活照", example = "front")
|
||||||
|
@RequestParam(required = false) String photoType) {
|
||||||
|
CustomerPhotoPreviewResult preview = customerManagementService.openCustomerPhotoPreview(url, id, photoType);
|
||||||
|
if (preview.getStatus() == CustomerPhotoPreviewResult.Status.NOT_FOUND) {
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
}
|
||||||
|
if (preview.getStatus() == CustomerPhotoPreviewResult.Status.BAD_REQUEST) {
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
}
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.parseMediaType(preview.getContentType()));
|
||||||
|
headers.setCacheControl("private, max-age=3600");
|
||||||
|
Resource resource = new InputStreamResource(preview.getInputStream());
|
||||||
|
return ResponseEntity.ok().headers(headers).body(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AudioManagement buildAudioRecordFromCustomer(CustomerManagement customer, LocalDateTime now) {
|
private AudioManagement buildAudioRecordFromCustomer(CustomerManagement customer, LocalDateTime now) {
|
||||||
|
|||||||
40
src/main/java/com/rj/dto/CustomerPhotoPreviewResult.java
Normal file
40
src/main/java/com/rj/dto/CustomerPhotoPreviewResult.java
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package com.rj.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户照片预览:从 MinIO 打开流的结果。
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public class CustomerPhotoPreviewResult {
|
||||||
|
|
||||||
|
public enum Status {
|
||||||
|
OK,
|
||||||
|
NOT_FOUND,
|
||||||
|
BAD_REQUEST
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Status status;
|
||||||
|
private final InputStream inputStream;
|
||||||
|
private final String contentType;
|
||||||
|
|
||||||
|
private CustomerPhotoPreviewResult(Status status, InputStream inputStream, String contentType) {
|
||||||
|
this.status = status;
|
||||||
|
this.inputStream = inputStream;
|
||||||
|
this.contentType = contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CustomerPhotoPreviewResult ok(InputStream inputStream, String contentType) {
|
||||||
|
return new CustomerPhotoPreviewResult(Status.OK, inputStream, contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CustomerPhotoPreviewResult notFound() {
|
||||||
|
return new CustomerPhotoPreviewResult(Status.NOT_FOUND, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CustomerPhotoPreviewResult badRequest() {
|
||||||
|
return new CustomerPhotoPreviewResult(Status.BAD_REQUEST, null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
34
src/main/java/com/rj/dto/CustomerPhotoUploadResult.java
Normal file
34
src/main/java/com/rj/dto/CustomerPhotoUploadResult.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package com.rj.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户照片上传至 MinIO 的结果,供控制器映射 HTTP 状态与 JSON。
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public class CustomerPhotoUploadResult {
|
||||||
|
|
||||||
|
private final int httpStatus;
|
||||||
|
private final boolean success;
|
||||||
|
private final String message;
|
||||||
|
private final String url;
|
||||||
|
|
||||||
|
private CustomerPhotoUploadResult(int httpStatus, boolean success, String message, String url) {
|
||||||
|
this.httpStatus = httpStatus;
|
||||||
|
this.success = success;
|
||||||
|
this.message = message;
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CustomerPhotoUploadResult ok(String url) {
|
||||||
|
return new CustomerPhotoUploadResult(200, true, "上传成功", url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CustomerPhotoUploadResult badRequest(String message) {
|
||||||
|
return new CustomerPhotoUploadResult(400, false, message, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CustomerPhotoUploadResult serverError(String message) {
|
||||||
|
return new CustomerPhotoUploadResult(500, false, message, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
package com.rj.service;
|
package com.rj.service;
|
||||||
|
|
||||||
import com.rj.entity.CustomerManagement;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.rj.dto.CustomerPhotoPreviewResult;
|
||||||
|
import com.rj.dto.CustomerPhotoUploadResult;
|
||||||
|
import com.rj.entity.CustomerManagement;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -13,4 +16,17 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||||||
*/
|
*/
|
||||||
public interface ICustomerManagementService extends IService<CustomerManagement> {
|
public interface ICustomerManagementService extends IService<CustomerManagement> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验客户存在后,将照片上传至 MinIO,返回访问 URL。
|
||||||
|
*/
|
||||||
|
CustomerPhotoUploadResult uploadCustomerPhoto(String id, MultipartFile file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 MinIO URL 或客户 ID + 照片类型解析对象并打开输入流,供预览下载。
|
||||||
|
*
|
||||||
|
* @param url 与上传接口返回一致的 MinIO 访问 URL,可为空
|
||||||
|
* @param id 客户 ID,与 photoType 联用时可空
|
||||||
|
* @param photoType front / side / life,与 id 联用时可空
|
||||||
|
*/
|
||||||
|
CustomerPhotoPreviewResult openCustomerPhotoPreview(String url, String id, String photoType);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,21 @@
|
|||||||
package com.rj.service.impl;
|
package com.rj.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.rj.config.MinIOConfig;
|
||||||
|
import com.rj.dto.CustomerPhotoPreviewResult;
|
||||||
|
import com.rj.dto.CustomerPhotoUploadResult;
|
||||||
import com.rj.entity.CustomerManagement;
|
import com.rj.entity.CustomerManagement;
|
||||||
import com.rj.mapper.CustomerManagementMapper;
|
import com.rj.mapper.CustomerManagementMapper;
|
||||||
import com.rj.service.ICustomerManagementService;
|
import com.rj.service.ICustomerManagementService;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.rj.service.MinIOService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -14,7 +25,190 @@ import org.springframework.stereotype.Service;
|
|||||||
* @author 李中华 ,spllzh
|
* @author 李中华 ,spllzh
|
||||||
* @since 2025-08-07
|
* @since 2025-08-07
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class CustomerManagementServiceImpl extends ServiceImpl<CustomerManagementMapper, CustomerManagement> implements ICustomerManagementService {
|
public class CustomerManagementServiceImpl extends ServiceImpl<CustomerManagementMapper, CustomerManagement>
|
||||||
|
implements ICustomerManagementService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MinIOService minIOService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MinIOConfig minioConfig;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CustomerPhotoUploadResult uploadCustomerPhoto(String id, MultipartFile file) {
|
||||||
|
try {
|
||||||
|
if (id == null || id.trim().isEmpty()) {
|
||||||
|
return CustomerPhotoUploadResult.badRequest("客户ID不能为空");
|
||||||
|
}
|
||||||
|
if (file == null || file.isEmpty()) {
|
||||||
|
return CustomerPhotoUploadResult.badRequest("请选择要上传的文件");
|
||||||
|
}
|
||||||
|
CustomerManagement customer = getById(id.trim());
|
||||||
|
if (customer == null) {
|
||||||
|
return CustomerPhotoUploadResult.badRequest("客户不存在");
|
||||||
|
}
|
||||||
|
String original = file.getOriginalFilename();
|
||||||
|
String ext = "";
|
||||||
|
if (original != null && original.contains(".")) {
|
||||||
|
ext = original.substring(original.lastIndexOf("."));
|
||||||
|
}
|
||||||
|
String objectName = "customer-management/photo/" + id.trim() + "/"
|
||||||
|
+ UUID.randomUUID().toString().replace("-", "") + ext;
|
||||||
|
String url = minIOService.uploadFileWithName(file, objectName);
|
||||||
|
log.info("客户照片已上传 MinIO,customerId={}, url={}", id, url);
|
||||||
|
return CustomerPhotoUploadResult.ok(url);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("客户照片上传失败: {}", e.getMessage(), e);
|
||||||
|
return CustomerPhotoUploadResult.serverError("上传失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CustomerPhotoPreviewResult openCustomerPhotoPreview(String url, String id, String photoType) {
|
||||||
|
String photoUrl = null;
|
||||||
|
if (url != null && !url.trim().isEmpty()) {
|
||||||
|
photoUrl = url.trim();
|
||||||
|
} else if (id != null && !id.trim().isEmpty() && photoType != null && !photoType.trim().isEmpty()) {
|
||||||
|
CustomerManagement customer = getById(id.trim());
|
||||||
|
if (customer == null) {
|
||||||
|
return CustomerPhotoPreviewResult.notFound();
|
||||||
|
}
|
||||||
|
String type = photoType.trim().toLowerCase();
|
||||||
|
switch (type) {
|
||||||
|
case "front":
|
||||||
|
photoUrl = customer.getFrontPhotoUrl();
|
||||||
|
break;
|
||||||
|
case "side":
|
||||||
|
photoUrl = customer.getSidePhotoUrl();
|
||||||
|
break;
|
||||||
|
case "life":
|
||||||
|
photoUrl = customer.getLifePhotoUrl();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return CustomerPhotoPreviewResult.badRequest();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return CustomerPhotoPreviewResult.badRequest();
|
||||||
|
}
|
||||||
|
if (photoUrl == null || photoUrl.trim().isEmpty()) {
|
||||||
|
return CustomerPhotoPreviewResult.notFound();
|
||||||
|
}
|
||||||
|
String loc = photoUrl.trim();
|
||||||
|
String nameProbe = lastPathSegmentForPreview(loc);
|
||||||
|
if (!isImageFile(nameProbe)) {
|
||||||
|
log.warn("预览拒绝非图片扩展名: {}", nameProbe);
|
||||||
|
return CustomerPhotoPreviewResult.badRequest();
|
||||||
|
}
|
||||||
|
String objectName = resolveMinioObjectNameForPreview(loc);
|
||||||
|
if (objectName == null || objectName.isEmpty()) {
|
||||||
|
log.warn("无法从 URL 解析 MinIO 对象名: {}", loc);
|
||||||
|
return CustomerPhotoPreviewResult.badRequest();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
InputStream inputStream = minIOService.downloadFile(objectName);
|
||||||
|
String contentType = imageContentType(nameProbe);
|
||||||
|
return CustomerPhotoPreviewResult.ok(inputStream, contentType);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("从 MinIO 读取客户照片失败, objectName={}", objectName, e);
|
||||||
|
return CustomerPhotoPreviewResult.notFound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String lastPathSegmentForPreview(String urlOrPath) {
|
||||||
|
if (urlOrPath == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String s = urlOrPath.trim();
|
||||||
|
int q = s.indexOf('?');
|
||||||
|
if (q >= 0) {
|
||||||
|
s = s.substring(0, q);
|
||||||
|
}
|
||||||
|
int slash = Math.max(s.lastIndexOf('/'), s.lastIndexOf('\\'));
|
||||||
|
return slash >= 0 ? s.substring(slash + 1) : s;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isImageFile(String fileName) {
|
||||||
|
if (fileName == null || fileName.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String ext = getFileExtension(fileName).toLowerCase();
|
||||||
|
switch (ext) {
|
||||||
|
case "jpg":
|
||||||
|
case "jpeg":
|
||||||
|
case "png":
|
||||||
|
case "gif":
|
||||||
|
case "webp":
|
||||||
|
case "bmp":
|
||||||
|
case "ico":
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getFileExtension(String fileName) {
|
||||||
|
if (fileName == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
int i = fileName.lastIndexOf('.');
|
||||||
|
return i >= 0 ? fileName.substring(i + 1) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String imageContentType(String fileName) {
|
||||||
|
String ext = getFileExtension(fileName).toLowerCase();
|
||||||
|
switch (ext) {
|
||||||
|
case "jpg":
|
||||||
|
case "jpeg":
|
||||||
|
return MediaType.IMAGE_JPEG_VALUE;
|
||||||
|
case "png":
|
||||||
|
return MediaType.IMAGE_PNG_VALUE;
|
||||||
|
case "gif":
|
||||||
|
return MediaType.IMAGE_GIF_VALUE;
|
||||||
|
case "webp":
|
||||||
|
return "image/webp";
|
||||||
|
case "bmp":
|
||||||
|
return "image/bmp";
|
||||||
|
case "ico":
|
||||||
|
return "image/x-icon";
|
||||||
|
default:
|
||||||
|
return MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolveMinioObjectNameForPreview(String fileUrl) {
|
||||||
|
if (fileUrl == null || fileUrl.trim().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String trimmed = fileUrl.trim();
|
||||||
|
String withoutQuery = trimmed;
|
||||||
|
int q = trimmed.indexOf('?');
|
||||||
|
if (q >= 0) {
|
||||||
|
withoutQuery = trimmed.substring(0, q);
|
||||||
|
}
|
||||||
|
String prefix = minioConfig.getFileUrlPrefix();
|
||||||
|
if (prefix != null && !prefix.isEmpty() && withoutQuery.startsWith(prefix)) {
|
||||||
|
return withoutQuery.substring(prefix.length());
|
||||||
|
}
|
||||||
|
return extractObjectNameFromUrlFallback(trimmed);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String extractObjectNameFromUrlFallback(String url) {
|
||||||
|
if (url == null || url.trim().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String urlWithoutParams = url.contains("?") ? url.substring(0, url.indexOf('?')) : url;
|
||||||
|
String[] parts = urlWithoutParams.split("/");
|
||||||
|
for (int i = parts.length - 1; i >= 0; i--) {
|
||||||
|
if (parts[i] != null && !parts[i].trim().isEmpty()) {
|
||||||
|
return parts[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user