mirror of
https://github.com/suyiiyii/SIMS.git
synced 2025-05-31 11:46:42 +08:00
commit
94bf792cd2
20
pom.xml
20
pom.xml
@ -95,16 +95,34 @@
|
||||
<artifactId>spring-restdocs-mockmvc</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webmvc-ui -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>2.3.0</version>
|
||||
<version>2.6.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-s3</artifactId>
|
||||
<version>1.12.706</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.11.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>4.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
17
src/main/java/top/suyiiyii/sims/common/S3Config.java
Normal file
17
src/main/java/top/suyiiyii/sims/common/S3Config.java
Normal file
@ -0,0 +1,17 @@
|
||||
package top.suyiiyii.sims.common;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import top.suyiiyii.sims.utils.S3Client;
|
||||
|
||||
@Configuration
|
||||
public class S3Config {
|
||||
@Bean
|
||||
public static S3Client Config(@Value("${S3.ENDPOINT}") String endpoint,
|
||||
@Value("${S3.ACCESS_KEY}") String accessKey,
|
||||
@Value("${S3.SECRET_KEY}") String secretKey,
|
||||
@Value("${S3.BUCKET}") String bucket) {
|
||||
return new S3Client(endpoint, accessKey, secretKey, bucket);
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package top.suyiiyii.sims.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import top.suyiiyii.sims.common.AuthAccess;
|
||||
import top.suyiiyii.sims.service.FileService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
public class FileController {
|
||||
@Autowired
|
||||
FileService fileService;
|
||||
|
||||
@AuthAccess(allowRoles = {"user"})
|
||||
@Operation(summary = "上传文件", description = "使用form-data格式\nfile:文件\nfilename: 文件名\n返回可访问的路径")
|
||||
@PostMapping("/upload")
|
||||
public String uploadFile(
|
||||
@Parameter String filename,
|
||||
@RequestBody(content = @Content(mediaType = "multipart/form-data",
|
||||
schema = @Schema(type = "string", format = "binary"))) MultipartFile file) {
|
||||
try (InputStream in = file.getInputStream()) {
|
||||
log.info("文件上传,文件名:{},描述:{}", file.getOriginalFilename(), filename);
|
||||
return fileService.uploadFile(in, filename);
|
||||
} catch (IOException e) {
|
||||
log.warn("文件上传失败", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
18
src/main/java/top/suyiiyii/sims/service/FileService.java
Normal file
18
src/main/java/top/suyiiyii/sims/service/FileService.java
Normal file
@ -0,0 +1,18 @@
|
||||
package top.suyiiyii.sims.service;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.suyiiyii.sims.utils.S3Client;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
@Service
|
||||
public class FileService {
|
||||
@Autowired
|
||||
private S3Client s3Client;
|
||||
|
||||
public String uploadFile(InputStream input,String fileName) {
|
||||
String extension = fileName.substring(fileName.lastIndexOf("."));
|
||||
return s3Client.uploadFile(input, extension);
|
||||
}
|
||||
}
|
123
src/main/java/top/suyiiyii/sims/utils/S3Client.java
Normal file
123
src/main/java/top/suyiiyii/sims/utils/S3Client.java
Normal file
@ -0,0 +1,123 @@
|
||||
package top.suyiiyii.sims.utils;
|
||||
|
||||
|
||||
import com.amazonaws.ClientConfiguration;
|
||||
import com.amazonaws.Protocol;
|
||||
import com.amazonaws.auth.AWSCredentials;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.AmazonS3Client;
|
||||
import com.amazonaws.services.s3.S3ClientOptions;
|
||||
import com.amazonaws.services.s3.model.ObjectMetadata;
|
||||
import com.amazonaws.services.s3.model.S3Object;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
public class S3Client {
|
||||
private final String endpoint;
|
||||
private final String bucket;
|
||||
private final AmazonS3 s3client;
|
||||
|
||||
public S3Client(String endpoint, String accessKey, String secretKey, String bucket) {
|
||||
this.endpoint = endpoint;
|
||||
this.bucket = bucket;
|
||||
URL endpointUrl;
|
||||
try {
|
||||
endpointUrl = new URL(endpoint);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String protocol = endpointUrl.getProtocol();
|
||||
int port = endpointUrl.getPort() == -1 ? endpointUrl.getDefaultPort() : endpointUrl.getPort();
|
||||
ClientConfiguration clientConfig = new ClientConfiguration();
|
||||
clientConfig.setSignerOverride("S3SignerType");
|
||||
clientConfig.setProtocol(Protocol.valueOf(protocol.toUpperCase()));
|
||||
// 禁用证书检查,避免https自签证书校验失败
|
||||
System.setProperty("com.amazonaws.sdk.disableCertChecking", "true");
|
||||
// 屏蔽 AWS 的 MD5 校验,避免校验导致的下载抛出异常问题
|
||||
System.setProperty("com.amazonaws.services.s3.disableGetObjectMD5Validation", "true");
|
||||
AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
|
||||
// 创建 S3Client 实例
|
||||
AmazonS3 s3client = new AmazonS3Client(awsCredentials, clientConfig);
|
||||
s3client.setEndpoint(endpointUrl.getHost() + ":" + port);
|
||||
s3client.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).build());
|
||||
this.s3client = s3client;
|
||||
}
|
||||
|
||||
|
||||
public boolean bucketExists(String bucket) {
|
||||
try {
|
||||
return s3client.doesBucketExist(bucket);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean existObject(String bucket, String objectId) {
|
||||
try {
|
||||
return s3client.doesObjectExist(bucket, objectId);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream download(String bucket, String objectId) {
|
||||
try {
|
||||
S3Object o = s3client.getObject(bucket, objectId);
|
||||
return o.getObjectContent();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void download(String bucket, String objectId, OutputStream out) {
|
||||
S3Object o = s3client.getObject(bucket, objectId);
|
||||
try (InputStream in = o.getObjectContent()) {
|
||||
IOUtils.copyLarge(in, out);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void upload(String bucket, String objectId, InputStream input) {
|
||||
try {
|
||||
// 创建文件上传的元数据
|
||||
ObjectMetadata meta = new ObjectMetadata();
|
||||
// 设置文件上传长度
|
||||
meta.setContentLength(input.available());
|
||||
// 上传
|
||||
s3client.putObject(bucket, objectId, input, meta);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public String uploadFile(InputStream input) {
|
||||
String objectID = UUID.randomUUID().toString();
|
||||
upload(bucket, objectID, input);
|
||||
return endpoint + "/" + bucket + "/" + objectID;
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收文件流,自动使用随机uuid命名并保留扩展名
|
||||
* 返回公网上可以直接访问的URL
|
||||
*
|
||||
* @param input 文件流
|
||||
* @param extensionName 扩展名
|
||||
* @return 文件的URL
|
||||
*/
|
||||
public String uploadFile(InputStream input, String extensionName) {
|
||||
String objectID = UUID.randomUUID() + extensionName;
|
||||
upload(bucket, objectID, input);
|
||||
return endpoint + "/" + bucket + "/" + objectID;
|
||||
}
|
||||
}
|
@ -2,6 +2,10 @@
|
||||
spring:
|
||||
profiles:
|
||||
active: prod
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 100MB
|
||||
max-request-size: 100MB
|
||||
datasource:
|
||||
url: ${DATASOURCE_URL}
|
||||
username: ${DATASOURCE_USERNAME}
|
||||
@ -14,4 +18,10 @@ auto-table:
|
||||
model-package: top.suyiiyii.sims.entity
|
||||
|
||||
jwt:
|
||||
secret: ${JWT_SECRET}
|
||||
secret: ${JWT_SECRET}
|
||||
|
||||
S3:
|
||||
ENDPOINT: ${S3_ENDPOINT}
|
||||
BUCKET: ${S3_BUCKET}
|
||||
ACCESS_KEY: ${S3_ACCESS_KEY}
|
||||
SECRET_KEY: ${S3_SECRET_KEY}
|
||||
|
@ -1,10 +1,14 @@
|
||||
package top.suyiiyii.sims.service;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import top.suyiiyii.sims.entity.Role;
|
||||
import top.suyiiyii.sims.utils.S3Client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -12,11 +16,15 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@SpringBootTest
|
||||
@ActiveProfiles("test")
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class RbacServiceTest {
|
||||
|
||||
@Autowired
|
||||
private RbacService rbacService;
|
||||
|
||||
@MockBean
|
||||
private S3Client s3Client;
|
||||
|
||||
@Test
|
||||
void addRoleWithUserId() {
|
||||
int userId = 1; // mock userId
|
||||
|
Loading…
x
Reference in New Issue
Block a user