package com.rongyichuang.judge;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import org.junit.jupiter.api.Test;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
import org.springframework.boot.test.web.server.LocalServerPort;
|
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.MediaType;
|
import org.springframework.http.ResponseEntity;
|
import org.springframework.test.context.ActiveProfiles;
|
|
import java.io.File;
|
import java.io.FileInputStream;
|
import java.io.IOException;
|
import java.net.http.HttpClient;
|
import java.net.http.HttpRequest;
|
import java.net.http.HttpResponse;
|
import java.net.URI;
|
import java.util.Collections;
|
import java.util.Map;
|
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
@ActiveProfiles("test")
|
public class JudgeRealCOSUploadTest {
|
|
@LocalServerPort
|
private int port;
|
|
@Autowired
|
private TestRestTemplate restTemplate;
|
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
|
@Test
|
void testRealCOSUpload() throws Exception {
|
System.out.println("=== 真实COS上传测试 ===");
|
|
// 步骤1: 获取真实的COS上传凭证
|
System.out.println("\n步骤1: 获取COS上传凭证");
|
Map<String, Object> credentials = getRealUploadCredentials();
|
|
if (credentials == null || credentials.isEmpty()) {
|
System.out.println("❌ 无法获取上传凭证,跳过真实上传测试");
|
return;
|
}
|
|
System.out.println("✅ 获取到上传凭证:");
|
credentials.forEach((key, value) -> {
|
if (key.contains("secret") || key.contains("token")) {
|
System.out.println(" " + key + ": " + maskSensitiveInfo(value.toString()));
|
} else {
|
System.out.println(" " + key + ": " + value);
|
}
|
});
|
|
// 步骤2: 准备上传文件
|
System.out.println("\n步骤2: 准备上传文件");
|
File logoFile = findLogoFile();
|
if (logoFile == null || !logoFile.exists()) {
|
System.out.println("❌ 找不到logo.png文件,跳过上传测试");
|
return;
|
}
|
|
System.out.println("✅ 找到logo文件: " + logoFile.getAbsolutePath());
|
System.out.println(" 文件大小: " + logoFile.length() + " bytes");
|
|
// 步骤3: 执行真实的COS上传
|
System.out.println("\n步骤3: 执行COS上传");
|
String uploadResult = performRealCOSUpload(credentials, logoFile);
|
|
if (uploadResult != null) {
|
System.out.println("✅ 文件上传成功!");
|
System.out.println(" 上传路径: " + uploadResult);
|
} else {
|
System.out.println("❌ 文件上传失败!");
|
}
|
}
|
|
/**
|
* 获取真实的COS上传凭证
|
*/
|
private Map<String, Object> getRealUploadCredentials() throws Exception {
|
String query = """
|
query {
|
getUploadCredentials {
|
bucket
|
region
|
key
|
presignedUrl
|
expiration
|
}
|
}
|
""";
|
|
try {
|
Map<String, String> request = Collections.singletonMap("query", query);
|
String response = postGraphQL(request);
|
|
Map<String, Object> responseMap = objectMapper.readValue(response, Map.class);
|
|
if (responseMap.containsKey("errors")) {
|
System.out.println("❌ GraphQL错误: " + responseMap.get("errors"));
|
return null;
|
}
|
|
Map<String, Object> data = (Map<String, Object>) responseMap.get("data");
|
return (Map<String, Object>) data.get("getUploadCredentials");
|
|
} catch (Exception e) {
|
System.out.println("❌ 获取上传凭证失败: " + e.getMessage());
|
e.printStackTrace();
|
return null;
|
}
|
}
|
|
/**
|
* 查找logo文件
|
*/
|
private File findLogoFile() {
|
// 尝试多个可能的路径
|
String[] possiblePaths = {
|
"UI/logo.png",
|
"../UI/logo.png",
|
"../../UI/logo.png",
|
"UI/logo.jpg",
|
"../UI/logo.jpg",
|
"../../UI/logo.jpg"
|
};
|
|
for (String path : possiblePaths) {
|
File file = new File(path);
|
if (file.exists()) {
|
return file;
|
}
|
}
|
|
return null;
|
}
|
|
/**
|
* 执行真实的COS上传(使用预签名URL)
|
*/
|
private String performRealCOSUpload(Map<String, Object> credentials, File file) {
|
try {
|
// 获取预签名URL
|
String presignedUrl = (String) credentials.get("presignedUrl");
|
String objectKey = (String) credentials.get("key");
|
|
if (presignedUrl == null || presignedUrl.isEmpty()) {
|
System.out.println("❌ 预签名URL为空");
|
return null;
|
}
|
|
System.out.println("预签名URL: " + presignedUrl);
|
System.out.println("对象键: " + objectKey);
|
|
// 读取文件内容
|
byte[] fileContent = readFileContent(file);
|
System.out.println("文件内容大小: " + fileContent.length + " bytes");
|
|
// 使用预签名URL直接上传,不需要额外的认证头部
|
HttpClient client = HttpClient.newHttpClient();
|
HttpRequest request = HttpRequest.newBuilder()
|
.uri(URI.create(presignedUrl))
|
.header("Content-Type", getContentType(file))
|
.PUT(HttpRequest.BodyPublishers.ofByteArray(fileContent))
|
.build();
|
|
// 发送请求
|
System.out.println("发送上传请求...");
|
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
|
System.out.println("响应状态码: " + response.statusCode());
|
System.out.println("响应头: " + response.headers().map());
|
if (!response.body().isEmpty()) {
|
System.out.println("响应体: " + response.body());
|
}
|
|
if (response.statusCode() == 200 || response.statusCode() == 201 || response.statusCode() == 204) {
|
System.out.println("✅ 文件上传成功!");
|
return objectKey;
|
} else {
|
System.out.println("❌ 上传失败,状态码: " + response.statusCode());
|
if (!response.body().isEmpty()) {
|
System.out.println("❌ 响应内容: " + response.body());
|
}
|
return null;
|
}
|
|
} catch (Exception e) {
|
System.out.println("❌ COS上传异常: " + e.getMessage());
|
e.printStackTrace();
|
return null;
|
}
|
}
|
|
/**
|
* 读取文件内容
|
*/
|
private byte[] readFileContent(File file) throws IOException {
|
try (FileInputStream fis = new FileInputStream(file)) {
|
return fis.readAllBytes();
|
}
|
}
|
|
/**
|
* 获取文件内容类型
|
*/
|
private String getContentType(File file) {
|
String fileName = file.getName().toLowerCase();
|
if (fileName.endsWith(".png")) {
|
return "image/png";
|
} else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
|
return "image/jpeg";
|
} else {
|
return "application/octet-stream";
|
}
|
}
|
|
|
|
/**
|
* 发送GraphQL请求
|
*/
|
private String postGraphQL(Map<String, String> request) throws Exception {
|
HttpHeaders headers = new HttpHeaders();
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
|
HttpEntity<Map<String, String>> entity = new HttpEntity<>(request, headers);
|
|
ResponseEntity<String> response = restTemplate.postForEntity(
|
"http://localhost:" + port + "/graphql", entity, String.class);
|
|
if (response.getStatusCode().is2xxSuccessful()) {
|
return response.getBody();
|
} else {
|
throw new RuntimeException("GraphQL request failed with status: " +
|
response.getStatusCode() + " and body: " + response.getBody());
|
}
|
}
|
|
/**
|
* 掩码敏感信息
|
*/
|
private String maskSensitiveInfo(String info) {
|
if (info == null || info.length() <= 8) {
|
return "****";
|
}
|
return info.substring(0, 4) + "****" + info.substring(info.length() - 4);
|
}
|
}
|