本地 测试文件上传下载;
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
package com.linke.product.interfaces.facade.menu;
|
package com.linke.product.interfaces.facade.menu;
|
||||||
|
|
||||||
import cn.hutool.core.io.resource.InputStreamResource;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.linke.product.application.service.menu.MenuApplicationService;
|
import com.linke.product.application.service.menu.MenuApplicationService;
|
||||||
import com.linke.product.domain.menu.entity.Menu;
|
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 org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import java.io.File;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.InputStream;
|
import java.io.*;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -210,8 +211,58 @@ public class MenuApi extends BaseController {
|
|||||||
return AjaxResult.success(menuApplicationService.uploadMinio(file));
|
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")
|
@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);
|
String fileKey = fileStorageService.uploadFile(file);
|
||||||
return AjaxResult.success(fileKey);
|
return AjaxResult.success(fileKey);
|
||||||
}
|
}
|
||||||
@@ -281,34 +332,36 @@ public class MenuApi extends BaseController {
|
|||||||
|
|
||||||
|
|
||||||
@PostMapping("/batchUpload")
|
@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) {
|
if (files == null || files.size() == 0) {
|
||||||
return AjaxResult.error("上传文件不能为空");
|
return AjaxResult.error("上传文件不能为空");
|
||||||
}
|
}
|
||||||
List<String> fileUrls = new ArrayList<>();
|
List<String> fileUrls = new ArrayList<>();
|
||||||
|
boolean localMode = isLocalNetwork(request);
|
||||||
for (MultipartFile multipartFile : files) {
|
for (MultipartFile multipartFile : files) {
|
||||||
String fileKey = fileStorageService.uploadFile(multipartFile);
|
if (localMode) {
|
||||||
fileUrls.add(fileKey);
|
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);
|
return AjaxResult.success(fileUrls);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/download")
|
@GetMapping("/download")
|
||||||
public ResponseEntity<InputStreamResource> downloadFromOBS(
|
public ResponseEntity<byte[]> downloadFromOBS(
|
||||||
@RequestParam String obsUrl,
|
@RequestParam String obsUrl,
|
||||||
@RequestParam String filename) {
|
@RequestParam String filename,
|
||||||
|
HttpServletRequest request) {
|
||||||
|
|
||||||
try {
|
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();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.add(HttpHeaders.CONTENT_DISPOSITION,
|
headers.add(HttpHeaders.CONTENT_DISPOSITION,
|
||||||
"attachment; filename=\"" + filename + "\"");
|
"attachment; filename=\"" + filename + "\"");
|
||||||
@@ -316,17 +369,49 @@ public class MenuApi extends BaseController {
|
|||||||
headers.add(HttpHeaders.PRAGMA, "no-cache");
|
headers.add(HttpHeaders.PRAGMA, "no-cache");
|
||||||
headers.add(HttpHeaders.EXPIRES, "0");
|
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();
|
String contentType = connection.getContentType();
|
||||||
MediaType mediaType = contentType != null ?
|
MediaType mediaType = contentType != null ?
|
||||||
MediaType.valueOf(contentType) :
|
MediaType.valueOf(contentType) :
|
||||||
MediaType.APPLICATION_OCTET_STREAM;
|
MediaType.APPLICATION_OCTET_STREAM;
|
||||||
|
headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileBytes.length));
|
||||||
// 5. 返回流式响应
|
|
||||||
return ResponseEntity.ok()
|
return ResponseEntity.ok()
|
||||||
.headers(headers)
|
.headers(headers)
|
||||||
.contentType(mediaType)
|
.contentType(mediaType)
|
||||||
.body(new InputStreamResource(inputStream));
|
.body(fileBytes);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("下载文件失败", e);
|
throw new RuntimeException("下载文件失败", e);
|
||||||
@@ -340,8 +425,31 @@ public class MenuApi extends BaseController {
|
|||||||
public ResponseEntity<StreamingResponseBody> downloadStreaming(
|
public ResponseEntity<StreamingResponseBody> downloadStreaming(
|
||||||
@RequestParam String bucketName,
|
@RequestParam String bucketName,
|
||||||
@RequestParam String objectKey,
|
@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()
|
return ResponseEntity.ok()
|
||||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||||
"attachment; filename=\"" + filename + "\"")
|
"attachment; filename=\"" + filename + "\"")
|
||||||
@@ -349,19 +457,9 @@ public class MenuApi extends BaseController {
|
|||||||
.body(outputStream -> {
|
.body(outputStream -> {
|
||||||
ObsClient obsClient1 = null;
|
ObsClient obsClient1 = null;
|
||||||
try {
|
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());
|
obsClient1 = new ObsClient(obsProperties.getAccessKey(), obsProperties.getSecretKey(), obsProperties.getEndpoint());
|
||||||
GetObjectRequest request = new GetObjectRequest(bucketName, objectKey);
|
GetObjectRequest req = new GetObjectRequest(bucketName, objectKey);
|
||||||
ObsObject obsObject = obsClient1.getObject(request);
|
ObsObject obsObject = obsClient1.getObject(req);
|
||||||
|
|
||||||
try (InputStream inputStream = obsObject.getObjectContent()) {
|
try (InputStream inputStream = obsObject.getObjectContent()) {
|
||||||
byte[] buffer = new byte[8192];
|
byte[] buffer = new byte[8192];
|
||||||
|
|||||||
Reference in New Issue
Block a user