zhaowenyu
2026-02-04 e9ed3967943149839c061b0821f7274899ed5e98
2026-02-04 优化minio上传,兼容minio所有接口的转发
2 files added
1 files deleted
320 ■■■■■ changed files
ard-admin/src/main/java/com/ard/web/controller/sample/media/MinioGeneralProxyController.java 118 ●●●●● patch | view | raw | blame | history
ard-admin/src/main/java/com/ard/web/controller/sample/media/MinioProxyUploadController.java 180 ●●●●● patch | view | raw | blame | history
ard-sample/src/main/java/com/ard/sample/config/RestTemplateConfig.java 22 ●●●●● patch | view | raw | blame | history
ard-admin/src/main/java/com/ard/web/controller/sample/media/MinioGeneralProxyController.java
New file
@@ -0,0 +1,118 @@
package com.ard.web.controller.sample.media;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.URI;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Enumeration;
@Slf4j
@Api(tags = "机场上传minio")
@RestController
@RequestMapping("/minioTransfer")
public class MinioGeneralProxyController {
    @Value("${oss.endpoint}")
    private String minioServerEndpoint;
    private final RestTemplate restTemplate;
    private static final String BASE_PREFIX = "/minioTransfer";
    public MinioGeneralProxyController(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }
    @ApiOperation("MinIO原生接口代理(无感中转)")
    @RequestMapping(value = "/**")
    public ResponseEntity<byte[]> proxyAllRequest(HttpServletRequest request) {
        try {
            // 1. 解析请求基础信息
            String methodStr = request.getMethod();
            String rawUri = URLDecoder.decode(request.getRequestURI(), StandardCharsets.UTF_8);
            String queryString = request.getQueryString();
            log.info("转发请求 | 方法:{} | URI:{} | 参数:{}", methodStr, rawUri, queryString);
            // 2. 构建MinIO目标地址
            String targetPath = rawUri.substring(BASE_PREFIX.length());
            StringBuilder targetUrl = new StringBuilder(minioServerEndpoint);
            targetUrl.append(targetPath);
            if (queryString != null && !queryString.isBlank()) {
                targetUrl.append("?").append(queryString);
            }
            URI uri = URI.create(targetUrl.toString());
            // 3. 转换为Spring标准HttpMethod(核心修复点)
            HttpMethod httpMethod = HttpMethod.valueOf(methodStr);
            // 4. 复制请求头+请求体
            HttpHeaders headers = copyRequestHeaders(request);
            byte[] requestBody = extractRequestBody(request);
            HttpEntity<byte[]> requestEntity = new HttpEntity<>(requestBody, headers);
            // 5. 修复exchange方法调用,匹配Spring官方重载方法
            ResponseEntity<byte[]> response = restTemplate.exchange(
                    uri,
                    httpMethod,
                    requestEntity,
                    byte[].class
            );
            log.info("转发成功 | 目标地址:{} | 状态码:{}", targetUrl, response.getStatusCode());
            // 原样回传所有响应信息
            return new ResponseEntity<>(
                    response.getBody(),
                    response.getHeaders(),
                    response.getStatusCode()
            );
        } catch (Exception e) {
            log.error("代理转发执行异常", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(("代理服务异常:" + e.getMessage()).getBytes(StandardCharsets.UTF_8));
        }
    }
    /**
     * 透传所有请求头
     */
    private HttpHeaders copyRequestHeaders(HttpServletRequest request) {
        HttpHeaders headers = new HttpHeaders();
        Enumeration<String> headerNames = request.getHeaderNames();
        if (headerNames == null) {
            return headers;
        }
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            Enumeration<String> values = request.getHeaders(name);
            headers.addAll(name, Collections.list(values));
        }
        // 移除Host头,避免转发地址冲突
        headers.remove(HttpHeaders.HOST);
        return headers;
    }
    /**
     * 读取请求体数据
     */
    private byte[] extractRequestBody(HttpServletRequest request) {
        try {
            return StreamUtils.copyToByteArray(request.getInputStream());
        } catch (IOException e) {
            log.warn("读取请求体失败", e);
            return new byte[0];
        }
    }
}
ard-admin/src/main/java/com/ard/web/controller/sample/media/MinioProxyUploadController.java
File was deleted
ard-sample/src/main/java/com/ard/sample/config/RestTemplateConfig.java
New file
@@ -0,0 +1,22 @@
package com.ard.sample.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        // 连接超时:10s
        factory.setConnectTimeout(10000);
        // 读取超时:5min(适配大文件上传/下载)
        factory.setReadTimeout(300000);
        // 开启流式请求,避免大文件加载到内存
        factory.setBufferRequestBody(false);
        return new RestTemplate(factory);
    }
}