工具类代码
(1)依赖导入:
<dependency>
<groupId>io.miniogroupId>
<artifactId>minioartifactId>
<version>8.3.7version>
dependency>
(2)MinioClient配置类
import org.springframework.context.annotation.*;
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
@Configuration
public class DataConfiguration {
@Value("${minio.minioUrl}")
private String minioUrl;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
@Bean
public MinioClient minioClient(){
return MinioClient.builder()
.endpoint(minioUrl)
.credentials(accessKey, secretKey)
.build();
}
}
(3)封装MinioUtils
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class MinioUtils {
/**
* minio上传文件
* @return
*/
public static Map<String,Object> uploadMinio(MultipartFile file,MinioClient minioClient,String minioUrl,String bucket) {
Map<String,Object> map= new HashMap<>();
String originalFilename = file.getOriginalFilename();
String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
if (StringUtils.equals(suffix,".png") || StringUtils.equals(suffix,".jpg")){
map.put("picType", 1);
}else {
//pdf
map.put("picType", 2);
}
//重置文件名
String newFileName=UUIDUtils.getRandomNumber()+suffix;
try {
if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build())){
//没有创建桶,默认创建桶
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
//自定义桶策略
setPolicy(minioClient,bucket);
}
PutObjectArgs objectArgs = PutObjectArgs.builder()
.object(newFileName)
.bucket(bucket)
.contentType(file.getContentType())
.stream(file.getInputStream(), file.getSize(), -1).build();
minioClient.putObject(objectArgs);
map.put("picName", newFileName);
map.put("httpPicUrl", minioUrl+bucket+"/"+newFileName);
map.put("fileSize", file.getSize());
return map;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* minio下载文件
* @param filename
* @param minioClient
* @param bucket
* @param res
*/
public static void downloads(String filename, MinioClient minioClient, String bucket, HttpServletResponse res){
GetObjectArgs objectArgs = GetObjectArgs.builder()
.bucket(bucket)
.object(filename).build();
try (GetObjectResponse response = minioClient.getObject(objectArgs)) {
byte[] buf = new byte[1024];
int len;
try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {
while ((len = response.read(buf)) != -1) {
os.write(buf, 0, len);
}
os.flush();
byte[] bytes = os.toByteArray();
res.setCharacterEncoding("utf-8");
res.setContentType("application/force-download");// 设置强制下载不打开
res.addHeader("Content-Disposition", "attachment;fileName=" + filename);
try (ServletOutputStream stream = res.getOutputStream()) {
stream.write(bytes);
stream.flush();
}
}
} catch (Exception e) {
log.info("服务器异常,下载失败");
}
}
/**
* minio 删除文件
* @param fileName
* @param minioClient
* @param bucket
*/
public static void deleteObject(String fileName,MinioClient minioClient,String bucket){
try {
minioClient.removeObject(RemoveObjectArgs.builder().
bucket(bucket).
object(fileName).build());
} catch (Exception e) {
log.info("服务器异常,删除失败");
e.printStackTrace();
}
}
/**
* 设置桶策略
* @param minioClient
* @param bu
*/
public static void setPolicy(MinioClient minioClient,String bucket){
StringBuilder builder=new StringBuilder();
String str = "{\n" +
" \"Version\":\"2012-10-17\",\n" +
" \"Statement\":[\n" +
" {\n" +
" \"Effect\":\"Allow\",\n" +
" \"Principal\":{\n" +
" \"AWS\":[\n" +
" \"*\"\n" +
" ]\n" +
" },\n" +
" \"Action\":[\n" +
" \"s3:GetBucketLocation\",\n" +
" \"s3:ListBucketMultipartUploads\"\n" +
" ],\n" +
" \"Resource\":[\n" +
" \"arn:aws:s3:::"+bucket+"\"\n" +
" ]\n" +
" },\n" +
" {\n" +
" \"Effect\":\"Allow\",\n" +
" \"Principal\":{\n" +
" \"AWS\":[\n" +
" \"*\"\n" +
" ]\n" +
" },\n" +
" \"Action\":[\n" +
" \"s3:PutObject\",\n" +
" \"s3:AbortMultipartUpload\",\n" +
" \"s3:DeleteObject\",\n" +
" \"s3:GetObject\",\n" +
" \"s3:ListMultipartUploadParts\"\n" +
" ],\n" +
" \"Resource\":[\n" +
" \"arn:aws:s3:::"+bucket+"/*\"\n" +
" ]\n" +
" }\n" +
" ]\n" +
"}";
builder.append(str);
//设置桶的权限
try {
minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(builder.toString()).build());
} catch (Exception e) {
e.printStackTrace();
}
}
}
(4)桶的策略有三种:
public:不需要access key 和 secret key,可以直接访问
private:需要 access key 和 secret key 才能访问
custom:不需要access key 和 secret key,但是只能以符合策略的方式来访问
默认创建桶的策略为private,是不能只能使用url打开图片的,在浏览器打开会出现下列错误。
可以通过console控制台,手动修改桶策略,但是手动处理只是下下策,我们实际开发中还是需要使用代码来控制桶的策略权限。
修改为public后,可以直接通过url打开图片或pdf。
输入ip+port+bucket后能够获取所有的该桶下的所有文件。显然是不安全的,那除了修改为public,还有一种方式设置外链访问,外联访问时间有效期为7天,还有一种就是设置自定义策略,也就是custom。
例如:上述工具类中的策略,设置没有listBucket权限。
设置后我们在输入ip+port+bucket,此时已经不能直接获取到所有的文件名了。
设置基于https协议请求
上述我们所直接访问的地址,是基于http协议请求,但是正式版小程序要求使用https请求,所以我们需要添加公钥和私钥来完成配置。
(1)下载certgen
wget https://github.com/minio/certgen/releases/latest/download/certgen-linux-amd64
(2)改名为certgen
mv certgen-linux-amd64 certgen
(3)修改权限
chmod a+x certgen
(4)执行命令生成公钥私钥
./certgen -host "ip1,ip2,ip3..."
(5)将生成的文件 ‘public.crt’, 'private.key’放到指定的minio的conf目录 /home/minio/conf
(6)在启动minio脚本中加上 (-certs-dir /home/minio/conf/)命令即可。再次访问console即可验证,添加密钥是否成功。
/home/minio/bin/minio server --config-dir /home/minio/conf/ -certs-dir /home/minio/conf/ --address ":9100" --console-address ":9002" \
(7)如图单机版:(注:多节点minio使用的密钥必须保持一致)
(8)多节点启动脚本
/home/minio/bin/minio server --config-dir /home/minio/conf/ -certs-dir /home/minio/conf/ --address ":9100" --console-address ":9001" \
https://192.168.1.227/home/minio/data \
https://192.168.1.228/home/minio/data \
(9)重启后,再次登录控制台,请求已经变成https,满足正式版小程序要求。
代码中设置minioClient跳过SSL认证,在配置类中修改,重启后直接访问url就可以。
当然这样还是以ip+port暴露,可以使用nignx代理地址。代理后直接通过:(域名+桶名+文件名)访问
@Bean
public MinioClient minioClient(){
OkHttpClient okHttpClent =null;
try {
okHttpClent = getUnsafeOkHttpClent();
} catch (Exception e) {
e.printStackTrace();
}
return MinioClient.builder().endpoint(minioUrl).credentials(accessKey,secretKey).httpClient(okHttpClent).build();
}
public static OkHttpClient getUnsafeOkHttpClent() throws Exception {
try {
final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
};
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new SecureRandom());
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
X509TrustManager x509TrustManager = Platform.get().platformTrustManager();
builder.sslSocketFactory(sslSocketFactory,x509TrustManager);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
return builder.build();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
``