IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> SpringBoot整合minio对象存储 -> 正文阅读

[游戏开发]SpringBoot整合minio对象存储

SpringBoot整合minio对象存储

一、导入依赖

	<!--minio的依赖配置-->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.2.1</version>
        </dependency>

二、编写配置类

1、MinioAPI.java

import io.minio.*;
import io.minio.http.Method;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.InputStream;


@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class MinioAPI {

	/**
	 * minio参数
	 */
	private String ENDPOINT;
	private String ACCESS_KEY;
	private String SECRET_KEY;

   /* private static final String ENDPOINT = "http://192.168.92.133:9000";
    private static final String ACCESS_KEY = "minioadmin";
    private static final String SECRET_KEY = "minioadmin";*/


	/**
	 * 桶占位符
	 */
	private static final String BUCKET_PARAM = "${bucket}";
	/**
	 * bucket权限-只读
	 */
	private static final String READ_ONLY = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetObject\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";
	/**
	 * bucket权限-只读
	 */
	private static final String WRITE_ONLY = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucketMultipartUploads\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";
	/**
	 * bucket权限-读写
	 */
	private static final String READ_WRITE = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";

	/**
	 * 文件url前半段
	 *
	 * @param bucket 桶
	 * @return 前半段
	 */
	public String getObjectPrefixUrl(String bucket) {
		return String.format("%s/%s/", ENDPOINT, bucket);
	}

	/**
	 * 创建桶
	 *
	 * @param bucket 桶
	 */
	public void makeBucket(String bucket) throws Exception {
		MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
		// 判断桶是否存在
		boolean isExist = client.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
		if (!isExist) {
			// 新建桶
			client.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
		}
	}

	/**
	 * 更新桶权限策略
	 *
	 * @param bucket 桶
	 * @param policy 权限
	 */
	public void setBucketPolicy(String bucket, String policy) throws Exception {
		MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
		switch (policy) {
			case "read-only":
				client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(READ_ONLY.replace(BUCKET_PARAM, bucket)).build());
				break;
			case "write-only":
				client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(WRITE_ONLY.replace(BUCKET_PARAM, bucket)).build());
				break;
			case "read-write":
				client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(READ_WRITE.replace(BUCKET_PARAM, bucket)).build());
				break;
			case "none":
			default:
				break;
		}
	}

	/**
	 * 上传本地文件
	 *
	 * @param bucket    桶
	 * @param objectKey 文件key
	 * @param filePath  文件路径
	 * @return 文件url
	 */
	public String uploadFile(String bucket, String objectKey, String filePath) throws Exception {
		MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
		client.uploadObject(UploadObjectArgs.builder().bucket(bucket).object(objectKey).filename(filePath).contentType("image/png").build());
		return getObjectPrefixUrl(bucket) + objectKey;
	}

	/**
	 * 流式上传文件
	 *
	 * @param bucket      桶
	 * @param objectKey   文件key
	 * @param inputStream 文件输入流
	 * @param contentType 文件输入流类型   
	 * @return 文件url
	 */
	public String uploadInputStream(String bucket, String objectKey, InputStream inputStream, String contentType) throws Exception {
		MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
		client.putObject(PutObjectArgs.builder().bucket(bucket).object(objectKey).stream(inputStream, inputStream.available(), -1).contentType(contentType).build());
		return getObjectPrefixUrl(bucket) + objectKey;
	}

	/**
	 * 下载文件
	 *
	 * @param bucket    桶
	 * @param objectKey 文件key
	 * @return 文件流
	 */
	public InputStream download(String bucket, String objectKey) throws Exception {
		MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
		return client.getObject(GetObjectArgs.builder().bucket(bucket).object(objectKey).build());
	}

	/**
	 * 文件复制
	 *
	 * @param sourceBucket    源桶
	 * @param sourceObjectKey 源文件key
	 * @param bucket          桶
	 * @param objectKey       文件key
	 * @return 新文件url
	 */
	public String copyFile(String sourceBucket, String sourceObjectKey, String bucket, String objectKey) throws Exception {
		MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
		CopySource source = CopySource.builder().bucket(sourceBucket).object(sourceObjectKey).build();
		client.copyObject(CopyObjectArgs.builder().bucket(bucket).object(objectKey).source(source).build());
		return getObjectPrefixUrl(bucket) + objectKey;
	}

	/**
	 * 删除文件
	 *
	 * @param bucket    桶
	 * @param objectKey 文件key
	 */
	public void deleteFile(String bucket, String objectKey) throws Exception {
		MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
		client.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectKey).build());
	}

	/**
	 * 获取文件签名url
	 *
	 * @param bucket    桶
	 * @param objectKey 文件key
	 * @param expires   签名有效时间  单位秒
	 * @return 文件签名地址
	 */
	public String getSignedUrl(String bucket, String objectKey, int expires) throws Exception {
		MinioClient client = MinioClient.builder().endpoint(ENDPOINT).credentials(ACCESS_KEY, SECRET_KEY).build();
		return client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucket).object(objectKey).expiry(expires).build());
	}


}

2、application.yml

minio:
  ENDPOINT: http://192.168.0.198:10004  #Minio服务所在地址
  ACCESS_KEY: minio #访问的key
  SECRET_KEY: dyminio123 #访问的秘钥

3、MinioConstants.java

public class MinioConstants {

	//图片,浏览器能预览
	public static final String IMAGE_JPG = "image/jpeg";
	public static final String IMAGE_PNG = "image/png";
	public static final String IMAGE_GIF = "image/gif";
	// pdf文档,浏览器能预览 application/pdf
	public static final String APPLICATION_PDF = "application/pdf";
	// 视频,浏览器能预览 video/mp4
	public static final String APPLICATION_MP4 = "video/mp4";
	// Wworld类型
	public static final String APPLICATION_WORD = "application/msword";
  	// 二进制流,不知道下载文件类型 application/octet-stream  
  	public static final String APPLICATION_STREAM = "application/octet-stream";
  
    /**
	 * 设置获取文件和图片的过期时间,expires签名有效时间  单位秒
	 */
	public static final Integer EXPIRES = 604800;

  
	/**
	 * 图片 桶
	 */
	public static final String BUCKET_IMG = "img";


	/**
	 * 文件 桶
	 */
	public static final String BUCKET_FILE = "file";

	/**
	 * 视频 桶
	 */
	public static final String BUCKET_VIDEO = "video";

	
}

三、代码示例(多文件)

1、上传文件

//设置多个文件
		if (!ObjectUtils.isEmpty(knFiles) && knFiles != null && knFiles.length > 0 && knFiles[0].getSize() > 0L) {

			//日期格式化
			Date d = new Date();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			String dateNowStr = sdf.format(d);
			//给文件和图片重新命名
			String datestr = dateNowStr + "/" + knowledgeId + "/" + dateNowStr + "-";

			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < knFiles.length; ++i) {
				String img = datestr + knFiles[i].getOriginalFilename();
				try {
					InputStream is = knFiles[i].getInputStream();
					this.minioAPI.uploadInputStream(MinioConstants.BUCKET_KNOWLEDGE_FILE, img, is, MinioConstants.APPLICATION_WORD);
				} catch (Exception e) {
					System.out.println("============上传文件失败=========");
					e.printStackTrace();
				}
				//把图片用逗号隔开
				if (sb.length() > 0) {
					sb.append(",");
				}
				sb.append(img);
			}
			String s = sb.toString();
			if (!StringUtils.isEmpty(knId) && knId!=" " && !knId.equals("null")) { //编辑/修改时保存之前的文件或者图片
				KnowledgeData byId = knowledgeDataService.getById(knId);
				if (byId != null && !StringUtils.isEmpty(byId.getKnFile())) {
					String knFiless = byId.getKnFile() + "," + s;
					knowledgeData.setKnFile(knFiless);
				} else {
					knowledgeData.setKnFile(s);
				}
			}else {
				knowledgeData.setKnFile(s);
			}

		}

2、查看文件

//获取文件
			String imgName = knowledgeData.getKnFile();
			if (imgName != null) {
				String[] imgs = imgName.split(",");
				Map<String,String> map = new HashMap<>();
				for (int i = 0; i < imgs.length; ++i) {
					try {
						String signedFileUrl = this.minioAPI.getSignedUrl(MinioConstants.BUCKET_KNOWLEDGE_FILE, imgs[i], MinioConstants.EXPIRES);
						String fileName = imgs[i].substring(imgs[i].lastIndexOf("-")+1);
						map.put(fileName,signedFileUrl);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				backListVO.setKnFiles(map);
			}

3、删除文件

/**
	 * 文件删除接口
	 */
	@PostMapping("/file/delete")
	@ApiOperation(value = "文件删除接口")
	@Transactional
	public R upload(@ApiParam(value = "文件名称") @RequestParam String fileName,
					@ApiParam(value = "主键knId") @RequestParam String knId) {

		KnowledgeData knowledgeData = new KnowledgeData();
		knowledgeData.setKnId(Integer.valueOf(knId));
		KnowledgeData byId = knowledgeDataService.getById(knId);
		if (byId!=null && !StringUtils.isEmpty(byId.getKnFile())){
			//获取文件
			String imgName = byId.getKnFile();
			if (imgName != null) {
				String[] imgs = imgName.split(",");
				StringBuilder sb = new StringBuilder();
				for (int i = 0; i < imgs.length; ++i) {
					String fileName1 = imgs[i].substring(imgs[i].lastIndexOf("-")+1);
					if (fileName.equals(fileName1)){
						//去掉删除文件
						try {
							minioAPI.deleteFile(MinioConstants.BUCKET_KNOWLEDGE_FILE,imgs[i]);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}else {
						//把图片用逗号隔开
						if (sb.length() > 0) {
							sb.append(",");
						}
						sb.append(imgs[i]);
						//files[i]=imgs[i];
					}
				}
				String s = sb.toString();
              	 //设置到数据库
				knowledgeData.setKnFile(s);
			}

		}
		boolean b = knowledgeDataService.updateById(knowledgeData);
		return R.status(b);
	}

四、查看、删除、上传和保留之前文件上传 代码封装

MInioUtils.java

import com.knowledge.base.enums.MinioConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author lyh
 * @date 2022-03-14
 */
public class MinioUtils {

	@Autowired
	private MinioAPI minioAPI;

	/**
	 * 获取访问的URL
	 * @param filePath  存入数据库中的文件目录名称(文件key),多个用逗号隔开
	 * @param bucket  桶
	 * @return 多文件名字和url
	 */
	private Map<String,String> getFileUrl(String filePath, String bucket){
		if (filePath != null) {
			String[] imgs = filePath.split(",");
			Map<String,String> map = new HashMap<>();
			for (int i = 0; i < imgs.length; ++i) {
				try {
					String signedFileUrl = this.minioAPI.getSignedUrl(bucket, imgs[i], MinioConstants.EXPIRES);
					String fileName = imgs[i].substring(imgs[i].lastIndexOf("-")+1);
					map.put(fileName,signedFileUrl);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			return map;
		}
		return null;
	}

	/**
	 * 删除文件
	 * @param filePath  存入数据库中的文件目录名称(文件key),多个用逗号隔开,从数据库查询
	 * @param fileName  从前端获取的文件名字
	 * @param bucket  桶
	 * @return 返回文件key,多个用逗号隔开
	 */
	private String deleteFile(String filePath, String fileName,  String bucket){
		if (filePath != null) {
			String[] imgs = filePath.split(",");
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < imgs.length; ++i) {
				String fileName1 = imgs[i].substring(imgs[i].lastIndexOf("-")+1);
				// 前端传入的文件名和数据库中的文件作比较
				if (fileName.equals(fileName1)){
					//去掉删除文件
					try {
						// 桶名、文件key
						minioAPI.deleteFile(bucket,imgs[i]);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}else {
					//把图片用逗号隔开
					if (sb.length() > 0) {
						sb.append(",");
					}
					sb.append(imgs[i]);
					//files[i]=imgs[i];
				}
			}
			String s = sb.toString();
			return s;
		}
		return null;
	}


	/**
	 * 可上传多个文件
	 * @param files
	 * @param bucket 桶
	 * @param contentType  文件类型
	 * @return 返回文件key,多个用逗号隔开
	 */
	private String upload(MultipartFile[] files, String bucket, String contentType){
		//设置多个文件上传
		if (!ObjectUtils.isEmpty(files) && files != null && files.length > 0 && files[0].getSize() > 0L) {
			//日期格式化
			Date d = new Date();
			SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
			String dateNowStr1 = sdf1.format(d);
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			String dateNowStr = sdf.format(d);
			//给文件和图片重新命名
			String datestr = dateNowStr1 + "/" + dateNowStr + "-";

			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < files.length; ++i) {
				String img = datestr + files[i].getOriginalFilename();
				try {
					InputStream is = files[i].getInputStream();
					this.minioAPI.uploadInputStream(bucket, img, is, contentType);
				} catch (Exception e) {
					System.out.println("============上传文件失败=========");
					e.printStackTrace();
				}
				//把图片用逗号隔开
				if (sb.length() > 0) {
					sb.append(",");
				}
				sb.append(img);
			}
			String s = sb.toString();
			return s;
		}
		return null;
	}

	/**
	 * 再次上传文件 不能覆盖之前的文件
	 * @param files
	 * @param bucket 桶
	 * @param contentType 文件类型
	 * @param filePath 存入数据库中的文件目录名称(文件key),多个用逗号隔开,从数据库查询
	 * @return filePath+现在上传的文件
	 */
	private String uploadEdit(MultipartFile[] files, String bucket, String contentType, String filePath){
		//设置多个文件上传
		if (!ObjectUtils.isEmpty(files) && files != null && files.length > 0 && files[0].getSize() > 0L) {
			//日期格式化
			Date d = new Date();
			SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
			String dateNowStr1 = sdf1.format(d);
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			String dateNowStr = sdf.format(d);
			//给文件和图片重新命名
			String datestr = dateNowStr1 + "/" + dateNowStr + "-";

			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < files.length; ++i) {
				String img = datestr + files[i].getOriginalFilename();
				try {
					InputStream is = files[i].getInputStream();
					this.minioAPI.uploadInputStream(bucket, img, is, contentType);
				} catch (Exception e) {
					System.out.println("============上传文件失败=========");
					e.printStackTrace();
				}
				//把图片用逗号隔开
				if (sb.length() > 0) {
					sb.append(",");
				}
				sb.append(img);
			}
			String s = sb.toString();
			if (!StringUtils.isEmpty(s)) {
				String filesStr = filePath + "," + s;
				return filesStr;
			} else {
				return s;
			}
		}
		return null;
	}
	
}

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 12:42:53  更:2022-04-04 12:43:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年10日历 -2024/10/30 17:22:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码