本地 测试文件上传下载;

This commit is contained in:
王奎兴
2026-08-04 09:30:13 +08:00
parent ef53355b87
commit df6b11a8bb
@@ -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<String> uploadFile(@RequestParam("file") MultipartFile file) {
public AjaxResult<String> 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<MultipartFile> files) {
public AjaxResult batchUpload(@RequestParam("files") List<MultipartFile> files, HttpServletRequest request) {
if (files == null || files.size() == 0) {
return AjaxResult.error("上传文件不能为空");
}
List<String> 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<InputStreamResource> downloadFromOBS(
public ResponseEntity<byte[]> 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<StreamingResponseBody> 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];