目录
MultipartFile可以提供哪些方法获取上传文件的信息?
接口说明:FileUploadController
@Tag(name = "文件管理")
@RequestMapping("/admin/file")
@RestController
public class FileUploadController {
@Autowired
private FileService service;
}
一、上传文件接口开发
首先我们先理解一下上传文件的流程:

接口名称:upload
请求方式:Post
请求路径:/admin/file/upload
请求参数:@RequestParam MultipartFile file
返回类型:String
需要自定义方法“upload”,进行实现上传文件功能,最后返回文件url给前端。
controller层:
@Operation(summary = "上传文件")
@PostMapping("upload")
public Result<String> upload(@RequestParam MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
String url=service.upload(file);
return Result.ok(url);
}
由于上传文件需要使用到MinIo,所以需要导入MinIo的依赖以及需要在"application.yml"配置MinIo。
依赖:
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
</dependency>
配置文件:
minio:
endpoint: http://192.168.10.101:9000
access-key: minioadmin
secret-key: minioadmin
bucket-name: lease
在做完以上步骤之后我们需要创建一个MinIo的配置类,把MinioClient注入SoringIoc容器中,方便进行调用。
为了方便维护MinIo的配置信息,我们还需创建一个MinIo的配置信息的类(MinioProperties):
@Data
@ConfigurationProperties(prefix = "minio")
public class MinioProperties {
private String endpoint;
private String accessKey;
private String secretKey;
private String bucketName;
}
@ConfigurationProperties注解:
标志这个类作为Configuration配置类的属性类,可以通过给"prefix"属性赋值,指定忽略配置文件的前缀。
创建MinioConfiguration类:
@Configuration
@EnableConfigurationProperties(MinioProperties.class)
public class MinioConfiguration {
@Autowired
private MinioProperties properties;
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(properties.getEndpoint()) //设置端点
.credentials(properties.getAccessKey(), properties.getSecretKey()) //设置用户名和密码
.build();
}
}
@EnableConfigurationProperties注解:
指定Minio的哪个配置属性类,如果没有这个注解,MinioProperties类会报错。
第二个注解@ConfigurationPropertiesScan("com.atguigu.lease.common.minio"):
有点类似@ComponentScan注解,通过指定包路径来映射配置属性类,这个注解适合拥有大量的配置属性类。
service层:
@Service
public class FileServiceImpl implements FileService {
@Autowired
private MinioProperties properties;
@Autowired
private MinioClient minioClient;
@Override
public String upload(MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(properties.getBucketName()).build());
if (!bucketExists) {
minioClient
.makeBucket(MakeBucketArgs.builder()
.bucket(properties.getBucketName())
.build());
minioClient
.setBucketPolicy(SetBucketPolicyArgs.builder()
.bucket(properties.getBucketName())
.config(createBucketPolicyConfig(properties.getBucketName()))
.build());
}
String filename = new SimpleDateFormat("yyyyMMdd").format(new Date()) +
"/" + UUID.randomUUID() + "-" + file.getOriginalFilename();
minioClient
.putObject(PutObjectArgs.builder()
.bucket(properties.getBucketName())
.stream(file.getInputStream(), file.getSize(), -1)
.object(filename)
.contentType(file.getContentType())
.build());
String url = String.join("/", properties.getEndpoint(), properties.getBucketName(), filename);
return url;
}
private String createBucketPolicyConfig(String bucketName) {
return """
{
"Statement" : [ {
"Action" : "s3:GetObject",
"Effect" : "Allow",
"Principal" : "*",
"Resource" : "arn:aws:s3:::%s/*"
} ],
"Version" : "2012-10-17"
}
""".formatted(bucketName);
}
}
👍实现逻辑:
- 注入先前配置好的MinioProperties和MinioClient。
- 判断MinIo中的"桶"是否已经存在,如果不存在则创建"桶"并且设置"桶"的权限(仅限自己可写入,所有人可以读)。
- 使用年月日+uuid+文件初始名字拼接起来作为文件名。
- 使用putObject方法(uploadObject方法只可以上传本地磁盘的文件)上传文件,其中需要使用MultipartFile的对象提供文件的属性信息进行设置。
- 拼接url:使用String类的join方法,把MinIo的端点、桶名字、文件名用"/"作为分隔符拼接起来。
- 返回url。
MultipartFile可以提供哪些方法获取上传文件的信息?
file.getSize():获取文件的大小 file.getOriginalFilename():获取文件的初始名字 file.getName():获取文件的上传后的名字 file.getInputStream():获取文件的输入流 file.getContentType():获取响应体中文件的类型
经测试,若不指定文件的ContentType,当访问文件的url时,此时浏览器会帮我们下载文件而不是访问文件内容。查看响应体,可知此时文件的ContentType为"application/octet-stream"的类型,这是一个流类型,而我们想要直接访问文件的内容,需要把ContentType设置为原来的类型,image/jpeg。
二、异常处理
当我们在服务器里把Minio的服务关掉之后,上传图片仍然显示为"200",但是数据却返回的是null,显然跟我们的实现逻辑并不符合,很显然我们需要进行异常的处理。
关闭minio服务:

测试显示仍然响应成功,但是数据却为null:

👍解决方法:进行全局异常处理。
如果不进行全局异常处理,所有的接口方法都需要写try-catch来进行异常处理,显然并不是最优的解法。
全局异常处理类:GlobalExceptionHandler
导入依赖:
<!--spring-web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public Result handle(Exception e){
e.printStackTrace();
return Result.fail();
}
}
注解解释:
@ControllerAdvice注解:用于声明处理全局Controller方法异常的类。 @ExceptionHandler注解:用于声明处理异常的方法,value属性用于声明该方法处理的异常类型 。 @ResponseBody注解:表示将方法的返回值作为HTTP的响应体。
1158

被折叠的 条评论
为什么被折叠?



