diff --git a/mhd_product/src/main/java/com/linke/product/interfaces/facade/menu/MenuApi.java b/mhd_product/src/main/java/com/linke/product/interfaces/facade/menu/MenuApi.java index e843d6cee..122211337 100644 --- a/mhd_product/src/main/java/com/linke/product/interfaces/facade/menu/MenuApi.java +++ b/mhd_product/src/main/java/com/linke/product/interfaces/facade/menu/MenuApi.java @@ -1,6 +1,5 @@ package com.linke.product.interfaces.facade.menu; -import cn.hutool.core.io.resource.InputStreamResource; import cn.hutool.core.util.StrUtil; import com.linke.product.application.service.menu.MenuApplicationService; import com.linke.product.domain.menu.entity.Menu; @@ -32,10 +31,12 @@ import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; import javax.annotation.PostConstruct; -import java.io.File; -import java.io.InputStream; +import javax.servlet.http.HttpServletRequest; +import java.io.*; import java.net.HttpURLConnection; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; @@ -210,8 +211,58 @@ public class MenuApi extends BaseController { return AjaxResult.success(menuApplicationService.uploadMinio(file)); }*/ + /** + * 判断调用方IP是否为内网环境(192.168开头) + */ + private boolean isLocalNetwork(HttpServletRequest request) { + String ip = request.getHeader("X-Forwarded-For"); + if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + // X-Forwarded-For 可能包含多个IP,取第一个 + if (ip != null && ip.contains(",")) { + ip = ip.split(",")[0].trim(); + } + return ip != null && ip.startsWith("192.168"); + } + + /** + * 本地上传文件到 D:/upload 目录 + */ + private String uploadToLocal(MultipartFile file) throws IOException { + String localUploadDir = "D:\\upload"; + File dir = new File(localUploadDir); + if (!dir.exists()) { + dir.mkdirs(); + } + String originalFilename = file.getOriginalFilename(); + String fileExtension = ""; + if (originalFilename != null && originalFilename.contains(".")) { + fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".")); + } + String fileName = UUID.randomUUID().toString() + fileExtension; + File destFile = new File(dir, fileName); + file.transferTo(destFile); + // 返回本地文件路径标识,格式: LOCAL:D:/upload/xxx.ext + return "LOCAL:" + destFile.getAbsolutePath(); + } + @PostMapping("/upload") - public AjaxResult uploadFile(@RequestParam("file") MultipartFile file) { + public AjaxResult uploadFile(@RequestParam("file") MultipartFile file, HttpServletRequest request) { + try { + if (isLocalNetwork(request)) { + String localPath = uploadToLocal(file); + return AjaxResult.success(localPath); + } + } catch (IOException e) { + return AjaxResult.error("本地上传文件失败: " + e.getMessage()); + } String fileKey = fileStorageService.uploadFile(file); return AjaxResult.success(fileKey); } @@ -281,34 +332,36 @@ public class MenuApi extends BaseController { @PostMapping("/batchUpload") - public AjaxResult batchUpload(@RequestParam("files") List files) { + public AjaxResult batchUpload(@RequestParam("files") List files, HttpServletRequest request) { if (files == null || files.size() == 0) { return AjaxResult.error("上传文件不能为空"); } List fileUrls = new ArrayList<>(); + boolean localMode = isLocalNetwork(request); for (MultipartFile multipartFile : files) { - String fileKey = fileStorageService.uploadFile(multipartFile); - fileUrls.add(fileKey); + if (localMode) { + try { + String localPath = uploadToLocal(multipartFile); + fileUrls.add(localPath); + } catch (IOException e) { + return AjaxResult.error("本地上传文件失败: " + e.getMessage()); + } + } else { + String fileKey = fileStorageService.uploadFile(multipartFile); + fileUrls.add(fileKey); + } } return AjaxResult.success(fileUrls); } @GetMapping("/download") - public ResponseEntity downloadFromOBS( + public ResponseEntity downloadFromOBS( @RequestParam String obsUrl, - @RequestParam String filename) { + @RequestParam String filename, + HttpServletRequest request) { try { - // 1. 连接到OBS临时URL - URL url = new URL(obsUrl); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("GET"); - - // 2. 获取输入流 - InputStream inputStream = connection.getInputStream(); - - // 3. 设置响应头 HttpHeaders headers = new HttpHeaders(); headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + filename + "\""); @@ -316,17 +369,49 @@ public class MenuApi extends BaseController { headers.add(HttpHeaders.PRAGMA, "no-cache"); headers.add(HttpHeaders.EXPIRES, "0"); - // 4. 根据文件类型设置Content-Type + // 判断是否为内网环境,从本地文件读取 + if (isLocalNetwork(request) && obsUrl != null && obsUrl.startsWith("LOCAL:")) { + String localFilePath = obsUrl.substring("LOCAL:".length()); + File localFile = new File(localFilePath); + if (!localFile.exists()) { + throw new RuntimeException("本地文件不存在: " + localFilePath); + } + byte[] fileBytes = Files.readAllBytes(localFile.toPath()); + String contentType = Files.probeContentType(localFile.toPath()); + MediaType mediaType = contentType != null ? + MediaType.valueOf(contentType) : + MediaType.APPLICATION_OCTET_STREAM; + headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileBytes.length)); + return ResponseEntity.ok() + .headers(headers) + .contentType(mediaType) + .body(fileBytes); + } + + // 连接OBS临时URL下载 + URL url = new URL(obsUrl); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + + InputStream inputStream = connection.getInputStream(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + baos.write(buffer, 0, bytesRead); + } + inputStream.close(); + byte[] fileBytes = baos.toByteArray(); + String contentType = connection.getContentType(); MediaType mediaType = contentType != null ? MediaType.valueOf(contentType) : MediaType.APPLICATION_OCTET_STREAM; - - // 5. 返回流式响应 + headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileBytes.length)); return ResponseEntity.ok() .headers(headers) .contentType(mediaType) - .body(new InputStreamResource(inputStream)); + .body(fileBytes); } catch (Exception e) { throw new RuntimeException("下载文件失败", e); @@ -340,8 +425,31 @@ public class MenuApi extends BaseController { public ResponseEntity downloadStreaming( @RequestParam String bucketName, @RequestParam String objectKey, - @RequestParam String filename) { + @RequestParam String filename, + HttpServletRequest request) { + // 判断是否为内网环境,从本地文件读取 + if (isLocalNetwork(request) && objectKey != null && objectKey.startsWith("LOCAL:")) { + String localFilePath = objectKey.substring("LOCAL:".length()); + File localFile = new File(localFilePath); + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, + "attachment; filename=\"" + filename + "\"") + .contentType(MediaType.APPLICATION_OCTET_STREAM) + .contentLength(localFile.length()) + .body(outputStream -> { + try (InputStream inputStream = new FileInputStream(localFile)) { + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); + } + outputStream.flush(); + } + }); + } + + // OBS方式下载 return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + filename + "\"") @@ -349,19 +457,9 @@ public class MenuApi extends BaseController { .body(outputStream -> { ObsClient obsClient1 = null; try { - System.out.println( - "AccessKey:" + obsProperties.getAccessKey() + - "SecretKey:" + obsProperties.getSecretKey() - + "Endpoint:" + obsProperties.getEndpoint() - ); - logger.error( - "AccessKey:" + obsProperties.getAccessKey() + - "SecretKey:" + obsProperties.getSecretKey() - + "Endpoint:" + obsProperties.getEndpoint() - ); obsClient1 = new ObsClient(obsProperties.getAccessKey(), obsProperties.getSecretKey(), obsProperties.getEndpoint()); - GetObjectRequest request = new GetObjectRequest(bucketName, objectKey); - ObsObject obsObject = obsClient1.getObject(request); + GetObjectRequest req = new GetObjectRequest(bucketName, objectKey); + ObsObject obsObject = obsClient1.getObject(req); try (InputStream inputStream = obsObject.getObjectContent()) { byte[] buffer = new byte[8192];