注:本文为学习时记录的笔记,内容尚浅,后续有时间可能会完善
1.导入Maven依赖
<!--minio分布式文件系统-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.4.3</version>
</dependency>
<!--okhttp客户端-->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.8.1</version>
</dependency>
2.在配置文件中定义连接配置
minio:
endpoint: http://xxxxxxx:9000 #minio服务地址
accessKey: kitie #账户
secretKey: xxxxxx #密码
bucket: #这里我们使用mediafiles和video两个桶
files: mediafiles
videofiles: video
3.读取配置文件,声明minio客户端bean
**
* @description minio配置
* @author LiuShiJie
* @date 2023/11/11
* @version 1.0
*/
@Configuration
public class MinioConfig {
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
// minio客户端bean
@Bean
public MinioClient minioClient() {
MinioClient minioClient =
MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
return minioClient;
}
}
4.编写业务层代码使用minio客户端实现文件上传(这里以service层和controller层部分代码为示例)
Controller层代码
/**
* @author LiuShiJie
* @version 1.0
* @description 媒资文件管理接口
* @date 2023/11/11
*/
@Api(value = "文件管理接口", tags = "文件管理接口")
@RestController
public class MediaFilesController {
@Autowired
MediaFileService mediaFileService;
@ApiOperation("上传文件")
@RequestMapping(value = "/upload/coursefile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ResponseBody
public UploadFileResultDto upload(@RequestPart("filedata") MultipartFile filedata, @RequestParam(value = "folder", required = false) String folder, @RequestParam(value = "objectName", required = false) String objectName) throws IOException {
// TODO 模拟信息
Long companyId = 1232141425L;
// 封装文件信息
UploadFileParamsDto uploadFileParamsDto = new UploadFileParamsDto();
//文件大小
uploadFileParamsDto.setFileSize(filedata.getSize());
//图片
uploadFileParamsDto.setFileType(DictionaryEnum.RESOURCE_TYPE_001001.getValue());
//文件名称
uploadFileParamsDto.setFilename(filedata.getOriginalFilename());//文件名称
//文件大小
long fileSize = filedata.getSize();
uploadFileParamsDto.setFileSize(fileSize);
//创建临时文件
File tempFile = File.createTempFile("minio", "temp");
//上传的文件拷贝到临时文件
filedata.transferTo(tempFile);
//文件路径
String absolutePath = tempFile.getAbsolutePath();
//上传文件
UploadFileResultDto uploadFileResultDto = mediaFileService.uploadFile(companyId, uploadFileParamsDto, absolutePath);
return uploadFileResultDto;
}
}
service层代码
/**
* @author LiuShiJie
* @version 1.0
* @description 媒体上传服务实现类
* @date 2023/11/11
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class MediaFileServiceImpl implements MediaFileService {
private final MediaFilesMapper mediaFilesMapper;
private final MinioClient minioClient;
//桶名称
@Value("${minio.bucket.files}")
private String bucket_files;
//获取文件默认存储目录路径 年/月/日
private String getDefaultFolderPath() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String folder = sdf.format(new Date()).replace("-", "/") + "/";
return folder;
}
//获取文件的md5
private String getFileMd5(File file) {
try (FileInputStream fileInputStream = new FileInputStream(file)) {
String fileMd5 = DigestUtils.md5Hex(fileInputStream);
return fileMd5;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//获取文件类型
private String getMimeType(String extension) {
if (extension == null)
extension = "";
//根据扩展名取出mimeType
ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(extension);
//通用mimeType,字节流
String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
if (extensionMatch != null) {
mimeType = extensionMatch.getMimeType();
}
return mimeType;
}
/**
* @param localFilePath 文件地址
* @param bucket 桶
* @param objectName 对象名称
* @return void
* @description 将文件写入minIO
* @author LiuShiJie
* @date 2023/11/11
*/
public boolean addMediaFilesToMinIO(String localFilePath, String mimeType, String bucket, String objectName) {
try {
UploadObjectArgs testbucket = UploadObjectArgs.builder()
.bucket(bucket)
.object(objectName)
.filename(localFilePath)
.contentType(mimeType)
.build();
minioClient.uploadObject(testbucket);
log.debug("上传文件到minio成功,bucket:{},objectName:{}", bucket, objectName);
System.out.println("上传成功");
return true;
} catch (Exception e) {
e.printStackTrace();
log.error("上传文件到minio出错,bucket:{},objectName:{},错误原因:{}", bucket, objectName, e.getMessage(), e);
CustomException.cast("上传文件到文件系统失败");
}
return false;
}
/**
* @param companyId 机构id
* @param fileMd5 文件md5值
* @param uploadFileParamsDto 上传文件的信息
* @param bucket 桶
* @param objectName 对象名称
* @return com.xuecheng.media.model.po.MediaFiles
* @description 将文件信息添加到数据库
* @author LiuShiJie
* @date 2023/11/11
*/
@Transactional
public MediaFiles addMediaFilesToDb(Long companyId, String fileMd5, UploadFileParamsDto uploadFileParamsDto, String bucket, String objectName) {
//从数据库查询文件
MediaFiles mediaFiles = mediaFilesMapper.selectById(fileMd5);
if (mediaFiles == null) {
mediaFiles = new MediaFiles();
//拷贝基本信息
BeanUtils.copyProperties(uploadFileParamsDto, mediaFiles);
mediaFiles.setId(fileMd5);
mediaFiles.setFileId(fileMd5);
mediaFiles.setCompanyId(companyId);
mediaFiles.setUrl("/" + bucket + "/" + objectName);
mediaFiles.setBucket(bucket);
mediaFiles.setFilePath(objectName);
mediaFiles.setCreateDate(LocalDateTime.now());
mediaFiles.setAuditStatus(DictionaryEnum.OBJECT_AUDIT_STATUS_002003.getValue());
mediaFiles.setStatus("1");
//保存文件信息到文件表
int insert = mediaFilesMapper.insert(mediaFiles);
if (insert < 0) {
log.error("保存文件信息到数据库失败,{}", mediaFiles.toString());
CustomException.cast("保存文件信息失败");
}
log.debug("保存文件信息到数据库成功,{}", mediaFiles.toString());
}
return mediaFiles;
}
@Transactional
@Override
public UploadFileResultDto uploadFile(Long companyId, UploadFileParamsDto uploadFileParamsDto, String localFilePath) {
File file = new File(localFilePath);
if (!file.exists()) {
CustomException.cast("文件不存在");
}
//获取文件名称
String filename = uploadFileParamsDto.getFilename();
//截取文件扩展名
String extension = filename.substring(filename.lastIndexOf("."));
//获取文件mimeType
String mimeType = getMimeType(extension);
//生成文件的md5值
String fileMd5 = getFileMd5(file);
//文件的默认目录(以日期为文件夹)
String defaultFolderPath = getDefaultFolderPath();
//存储到minio中的对象名(带目录)
String objectName = defaultFolderPath + fileMd5 + extension;
//将文件上传到minio
boolean b = addMediaFilesToMinIO(localFilePath, mimeType, bucket_files, objectName);
//文件大小
uploadFileParamsDto.setFileSize(file.length());
//将文件信息存储到数据库
MediaFiles mediaFiles = addMediaFilesToDb(companyId, fileMd5, uploadFileParamsDto, bucket_files, objectName);
//返回媒体数据
UploadFileResultDto uploadFileResultDto = new UploadFileResultDto();
BeanUtils.copyProperties(mediaFiles, uploadFileResultDto);
return uploadFileResultDto;
}
}
5.运行程序,测试api
测试api这里我们使用idea的httpClient插件(也可用Postman,ApiFox等工具)
media-api.http文件内容如下
### 上传文件
POST {{服务路径}}/media/upload/coursefile
Content-Type: multipart/form-data; boundary=WebAppBoundary
--WebAppBoundary
Content-Disposition: form-data; name="filedata"; filename="这里为文件名.txt"
Content-Type: application/octet-stream
< d:/test.png
< d:/downlaodtest.json 意思为上传本机D盘的downlaodtest.json文件
请求成功后可看到对应bucket桶中新增了对应文件
后续可通过 minio服务url + bucket/xxx/文件名访问对应文件