文章目录
基本所有的软件项目都会需要文件存储功能,图片、视频存储。
几种常用的文件存储
经常用的几种方案,直接存在本地文件夹,开发一个简单的系统当然没有问题。随机系统所需的资源变多,这种情况显然是不可能的。这种适合做一个简单的demo,毕设之类的的系统。
使用第三方的存储服务,如阿里云的oss,十分的方便管理。但是是收费的,如果经费充足也可以考虑。
使用HDFS ,分布式文件存储放方案,大数据领域的文件存储框架,过程配置很繁琐,对于新手来说很不友好。
minio 是一个非常轻量的服务,可以很简单的和其他应用的结合使用,它兼容亚马逊 S3 云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等。
还提供了许多语言的SDK,开发较为方便。
MinIO集群采用去中心化共享架构,每个结点是对等关系,通过Nginx可对MinIO进行负载均衡访问。
安装和使用minio
在linux上面配置mioio过于繁琐。在windows上面也可以运行。
minio的官网:dl.min.io/server/minio/release/windows-amd64/
首先下载minio,下载后是一个.exe文件
在cmd窗口中运行
java
//minio.exe server 启动服务器 后面是对应的节点也就是数据存储的位置,如果上线了就是服务器的地址
minio.exe server E:\develop\data\data1 E:\develop\data\data2 E:\develop\data\data3 E:\develop\data\data4
访问mino
java
在浏览器中输入:http://localhost:9000 跳转到登录页面 账号和密码都是 minioadmin
登录进去后;
设置bucket为公有public,可以外部进行访问的。
文件的地址就是 ip地址+端口号9000+文件的相对地址
SpringBoot整合minio
1.导入minio的maven坐标。
java
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.4.3</version>
</dependency>
2.配置yml文件
minio:
endpoint: http://127.0.0.1:9000 #文件的前缀 数据存储文件地址应该是相对地址,便于以后更换服务器
accessKey: minioadmin
secretKey: minioadmin
bucket:
files: mediafiles
videofiles: video
在springBootTest中编写程序
//创建一个minioClient
static MinioClient minioClient =
MinioClient.builder()
.endpoint("http://127.0.0.1:9000")
.credentials("minioadmin", "minioadmin")
.build();
3.注册bean,需要用minclient。
java
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//注入到bean中去
@Configuration
public class MinioConfig {
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}
FileController
java
import com.j256.simplemagic.ContentInfo;
import com.j256.simplemagic.ContentInfoUtil;
import com.njitzx.service.FileService;
import com.njitzx.util.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
@RestController
@RequestMapping(value = "/upload")
@Slf4j
public class FileController {
private String bucket = "bucket";
@Autowired
private FileService fileService;
@Value("${minio.endpoint}")
private String endpoint;
/**
* 要有一个文件存储的目录?如果判断文件是否已经存在
*/
/**
* file 前端传过来的文件
*/
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Result<String> upload(@RequestParam("file") MultipartFile file) throws Exception {
log.info("开始上传文件");
System.out.println(file.getOriginalFilename());
String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
File tempFile = File.createTempFile("temp", suffix);
file.transferTo(tempFile);
String floadName = fileService.upload(tempFile);
String url = endpoint + "/" + bucket + "/" + floadName;
return Result.success(url);
}
public static 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;
}
/**
* 删除文件
*/
}
java
import com.j256.simplemagic.ContentInfo;
import com.j256.simplemagic.ContentInfoUtil;
import com.njitzx.service.FileService;
import io.minio.MinioClient;
import io.minio.UploadObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import java.io.File;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
@Service
@Slf4j
public class FileServiceImpl implements FileService {
@Autowired
MinioClient minioClient;
private String bucket = "bucket";
@Override
public String upload(File tempFile) {
String filename = tempFile.getName();
System.out.println(filename);
String extension = filename.substring(filename.lastIndexOf("."));
String objectname = getDefaultFolderPath() + getFileMd5(tempFile) + extension;
System.out.println(objectname);
try {
UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder()
.bucket(bucket).
object(objectname).
filename(tempFile.getAbsolutePath()).contentType(getMimeType(extension)).build();
minioClient.uploadObject(uploadObjectArgs);
log.info("上传成功");
return objectname;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static 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;
}
public static String getFileMd5(File file) {
try {
FileInputStream fileInputStream = new FileInputStream(file);
String filemd5 = DigestUtils.md5DigestAsHex(fileInputStream);
return filemd5;
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
private String getDefaultFolderPath() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String folder = sdf.format(new Date()).replaceAll("-", "/") + "/";
return folder;
}
}