哪个公司的网站做得好,男女朋友在一起做那个的网站,企业服务云平台,wordpress手机版切换华为云云服务器评测|基于云服务器的minio部署手册
【软件安装版本】【集群安装#xff08;是#xff09;#xff08;否#xff09;】 版本 创建人 修改人 创建时间 备注 1.0 jz jz 2023.9.2 minio华为云耀服务器 一. 部署规划与架构
1. 规…华为云云服务器评测|基于云服务器的minio部署手册
【软件安装版本】【集群安装是否】 版本 创建人 修改人 创建时间 备注 1.0 jz jz 2023.9.2 minio华为云耀服务器 一. 部署规划与架构
1. 规划集群网络规划服务器规划 安装方式 非集群安装 服务器 华为云192.168.0.147 端口号 A.minio管理界面900033806 B.demo应用8081
2. 架构集群拓扑图 3. 支撑业务 小文件服务器图片文件视频的存储管理。
二. 运行环境安装
硬件 华为云耀服务器2核2G 3m网络 2. 操作系统 uname -a 为了springboot的demo运行需要提前安装好Java运行环境。这里不再重述 3. 环境配置 软件安装路径/opt/software/minio mkdir -p /opt/software/minio 数据文件路径/opt/data/minio mkdir -p /opt/data/minio 日志文件路径: /opt/data/minio/logs mkdir -p /opt/data/minio/logs 三. 单机部署步骤
安装包获取与安装 下载地址;https://min.io/download#/linux cd /opt/software/minio/ wget https://dl.min.io/server/minio/release/linux-amd64/minio 安装成功 查看下载文件 ls 2. 配置修改 vim /etc/default/minio # 启动的时候看提示 新版本 MINIO_ROOT_USERusername MINIO_ROOT_PASSWORDpassword # 如果MinIO版本比较旧修改用户名密码为 MINIO_ACCESS_KEYusername MINIO_SECRET_KEYpassword 注意创建的文件是个新文件。
修改环境变量 vim /etc/profile
增加两行 export MINIO_ROOT_USERusername export MINIO_ROOT_PASSWORDpassword # 如果MinIO版本比较旧修改用户名密码为 export MINIO_ACCESS_KEYusername export MINIO_SECRET_KEYpassword 配置文件生效 source /etc/profile 3. 检测依赖环境是否就绪 java -version 4.安装 赋予文件安装权限 chmod 777 minio ls -l 以守护进程方式启动指定端口为9000固定端口数据文件路径/opt/data/minio/ nohup /opt/software/minio/minio server --console-address :33806 --address 0.0.0.0:9000 /opt/data/minio /opt/data/minio/logs/minio.log ps -ef |grep minio more minio.log Minio启动成功 5. 云服务器开通公网端口号9000 登录华为云账号https://auth.huaweicloud.com/ 配置到服务器 进入控制台更改安全组 选择刚才创建的安全组 验证 浏览器输入公网ip:9000
会自动跳转到33806端口上。 用username/password登录 四.应用部署 1. 安装java 请自行安装jdk文件保证java -version可用。 2.编写项目 Pom文件中增加配置 !--MinIO JAVA SDK-- dependency groupIdio.minio/groupId artifactIdminio/artifactId version${minio.version}/version /dependency
Yaml中增加配置 minio: endpoint: http://192.168.0.213:9000 #MinIO服务所在地址 bucketName: mall #存储桶名称 bucketImg: img # 图片桶 bucketVideo: video # 视频桶 accessKey: fileadmin #访问的key secretKey: fileadmin #访问的秘钥
编写工具类 package top.fairy.global.globalfairytoppi4j.utils; import io.minio.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import top.fairy.global.globalfairytoppi4j.beans.ResultEntity; import top.fairy.global.globalfairytoppi4j.config.MinioClientConfig; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Map; Slf4j Component public class MinioUtil { /** * Minio文件上传 * * param file 文件实体 * param fileName 修饰过的文件名 非源文件名 * param bucketName 所存文件夹桶名 * return */ public ResultEntityMapString, Object minioUpload(MultipartFile file, String fileName, String bucketName) { ResultEntityMapString, Object resultEntity new ResultEntity(); try { MinioClient minioClient MinioClientConfig.getMinioClient(); // fileName为空说明要使用源文件名上传 if (fileName null) { fileName file.getOriginalFilename(); fileName fileName.replaceAll( , _); } InputStream inputStream file.getInputStream(); PutObjectArgs objectArgs PutObjectArgs.builder().bucket(bucketName).object(fileName) .stream(inputStream, file.getSize(), -1).contentType(file.getContentType()).build(); //文件名称相同会覆盖 minioClient.putObject(objectArgs); return resultEntity; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 检查存储桶是否存在 * * param bucketName 存储桶名称 * return */ public boolean bucketExists(String bucketName) { boolean flag false; try { flag MinioClientConfig.bucketExists(bucketName); if (flag) { return true; } } catch (Exception e) { e.printStackTrace(); return false; } return false; } /** * 获取文件流 * * param fileName 文件名 * param bucketName 桶名文件夹 * return */ public InputStream getFileInputStream(String fileName, String bucketName) { try { MinioClient minioClient MinioClientConfig.getMinioClient(); return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build()); } catch (Exception e) { e.printStackTrace(); log.error(e.getMessage()); } return null; } /** * param bucketName: * author * description: 创建桶 * date 2022/8/16 14:36 */ public void createBucketName(String bucketName) { try { if (StringUtils.isBlank(bucketName)) { return; } MinioClient minioClient MinioClientConfig.getMinioClient(); boolean isExist MinioClientConfig.bucketExists(bucketName); if (isExist) { log.info(Bucket {} already exists., bucketName); } else { minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); } } catch (Exception e) { e.printStackTrace(); log.error(e.getMessage()); } } /** * 下载文件 * * param originalName 文件路径 */ public InputStream downloadFile(String bucketName, String originalName, HttpServletResponse response) { try { MinioClient minioClient MinioClientConfig.getMinioClient(); InputStream file minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(originalName).build()); String filename new String(originalName.getBytes(ISO8859-1), StandardCharsets.UTF_8); if (StringUtils.isNotBlank(originalName)) { filename originalName; } response.setHeader(Content-Disposition, attachment;filename filename); ServletOutputStream servletOutputStream response.getOutputStream(); int len; byte[] buffer new byte[1024]; while ((len file.read(buffer)) 0) { servletOutputStream.write(buffer, 0, len); } servletOutputStream.flush(); file.close(); servletOutputStream.close(); return file; } catch (Exception e) { e.printStackTrace(); return null; } } /** * param bucketName: * description: 删除桶 * date 2022/8/16 14:36 */ public void deleteBucketName(String bucketName) { try { if (StringUtils.isBlank(bucketName)) { return; } MinioClient minioClient MinioClientConfig.getMinioClient(); boolean isExist MinioClientConfig.bucketExists(bucketName); if (isExist) { minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build()); } } catch (Exception e) { e.printStackTrace(); log.error(e.getMessage()); } } /** * param bucketName: * description: 删除桶下面所有文件 * date 2022/8/16 14:36 */ public void deleteBucketFile(String bucketName) { try { if (StringUtils.isBlank(bucketName)) { return; } MinioClient minioClient MinioClientConfig.getMinioClient(); boolean isExist minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); if (isExist) { minioClient.deleteBucketEncryption(DeleteBucketEncryptionArgs.builder().bucket(bucketName).build()); } } catch (Exception e) { e.printStackTrace(); log.error(e.getMessage()); } } /** * 根据文件路径得到预览文件绝对地址 * * param bucketName * param fileName * return */ public String getPreviewFileUrl(String bucketName, String fileName) { try { MinioClient minioClient MinioClientConfig.getMinioClient(); return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(fileName).build()); } catch (Exception e) { e.printStackTrace(); return ; } } }
编写配置文件 package top.fairy.global.globalfairytoppi4j.config; import io.minio.BucketExistsArgs; import io.minio.MinioClient; import io.minio.messages.Bucket; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.List; Slf4j Component Configuration public class MinioClientConfig { Autowired private StorageProperty storageProperty; private static MinioClient minioClient; /** * description: 获取minioClient * date 2021/6/22 16:55 * return io.minio.MinioClient */ public static MinioClient getMinioClient(){ return minioClient; } /** * 判断 bucket是否存在 * * param bucketName: * 桶名 * return: boolean * date : 2020/8/16 20:53 */ SneakyThrows(Exception.class) public static boolean bucketExists(String bucketName) { return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); } /** * 获取全部bucket * * param : * return: java.util.Listio.minio.messages.Bucket * date : 2020/8/16 23:28 */ SneakyThrows(Exception.class) public static ListBucket getAllBuckets() { return minioClient.listBuckets(); } /** * 初始化minio配置 * * param : * return: void * date : 2020/8/16 20:56 */ PostConstruct public void init() { try { minioClient MinioClient.builder() .endpoint(storageProperty.getEndpoint()) .credentials(storageProperty.getAccessKey(), storageProperty.getSecretKey()) .build(); } catch (Exception e) { e.printStackTrace(); log.error(初始化minio配置异常: 【{}】, e.fillInStackTrace()); } } }
编写业务类 package top.fairy.global.globalfairytoppi4j.action; import cn.hutool.core.collection.CollUtil; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSONObject; import com.fasterxml.jackson.databind.ObjectMapper; import io.minio.*; import io.minio.errors.*; import io.minio.messages.Bucket; import io.minio.messages.Item; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import top.fairy.global.globalfairytoppi4j.api.CommonResult; import top.fairy.global.globalfairytoppi4j.beans.BucketPolicyConfigDto; import top.fairy.global.globalfairytoppi4j.beans.FileVo; import top.fairy.global.globalfairytoppi4j.beans.MinioUploadDto; import top.fairy.global.globalfairytoppi4j.beans.PageUtil; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.ArrayList; import java.util.Comparator; import java.util.Date; import java.util.List; /** * MinIO对象存储管理 * Created by macro on 2019/12/25. */ //Api(tags MinioController, description MinIO对象存储管理) Controller RequestMapping(/minio) public class MinioController { private static final Logger LOGGER LoggerFactory.getLogger(MinioController.class); Value(${minio.endpoint}) private String ENDPOINT; Value(${minio.bucketName}) private String BUCKET_NAME; Value(${minio.bucketImg}) private String BUCKET_IMG; Value(${minio.bucketVideo}) private String BUCKET_VIDEO; Value(${minio.accessKey}) private String ACCESS_KEY; Value(${minio.secretKey}) private String SECRET_KEY; // ApiOperation(文件上传) RequestMapping(value /upload, method RequestMethod.POST) ResponseBody public CommonResult upload(RequestPart(file) MultipartFile file) { try { //创建一个MinIO的Java客户端 MinioClient minioClient MinioClient.builder() .endpoint(ENDPOINT) .credentials(ACCESS_KEY,SECRET_KEY) .build(); boolean isExist minioClient.bucketExists(BucketExistsArgs.builder().bucket(BUCKET_NAME).build()); if (isExist) { LOGGER.info(存储桶已经存在); } else { //创建存储桶并设置只读权限 minioClient.makeBucket(MakeBucketArgs.builder().bucket(BUCKET_NAME).build()); BucketPolicyConfigDto bucketPolicyConfigDto createBucketPolicyConfigDto(BUCKET_NAME); SetBucketPolicyArgs setBucketPolicyArgs SetBucketPolicyArgs.builder() .bucket(BUCKET_NAME) .config(JSONUtil.toJsonStr(bucketPolicyConfigDto)) .build(); minioClient.setBucketPolicy(setBucketPolicyArgs); } String filename file.getOriginalFilename(); SimpleDateFormat sdf new SimpleDateFormat(yyyyMMdd); // 设置存储对象名称 String objectName sdf.format(new Date()) / filename; // 使用putObject上传一个文件到存储桶中 PutObjectArgs putObjectArgs PutObjectArgs.builder() .bucket(BUCKET_NAME) .object(objectName) .contentType(file.getContentType()) .stream(file.getInputStream(), file.getSize(), ObjectWriteArgs.MIN_MULTIPART_SIZE).build(); minioClient.putObject(putObjectArgs); LOGGER.info(文件上传成功!); MinioUploadDto minioUploadDto new MinioUploadDto(); minioUploadDto.setName(filename); minioUploadDto.setUrl(ENDPOINT / BUCKET_NAME / objectName); return CommonResult.success(minioUploadDto); } catch (Exception e) { e.printStackTrace(); LOGGER.info(上传发生错误: {}, e.getMessage()); } return CommonResult.failed(); } private BucketPolicyConfigDto createBucketPolicyConfigDto(String bucketName) { BucketPolicyConfigDto.Statement statement BucketPolicyConfigDto.Statement.builder() .Effect(Allow) .Principal(*) .Action(s3:GetObject) .Resource(arn:aws:s3:::bucketName/*.**).build(); return BucketPolicyConfigDto.builder() .Version(2012-10-17) .Statement(CollUtil.toList(statement)) .build(); } /** * 获取文件列表 * * param pageNum 页码 * param pageSize 一页的数量 * return * throws Exception */ ResponseBody RequestMapping(value /fileList, method RequestMethod.GET, produces application/json;charsetUTF-8) public String getFileList(Integer pageNum, Integer pageSize) throws Exception { String bucketName img; //创建一个MinIO的Java客户端 MinioClient minioClient MinioClient.builder() .endpoint(ENDPOINT) .credentials(ACCESS_KEY,SECRET_KEY) .build(); DecimalFormat df new DecimalFormat(0.00); ListBucket buckets minioClient.listBuckets(); ListFileVo list new ArrayList(32); if (!buckets.isEmpty()) { buckets.forEach(s - { try { // 得到bucket下的文件 IterableResultItem results minioClient.listObjects(s.name()); // 循环遍历获取每一个文件对象 results.forEach(g - { try { FileVo fileVo new FileVo(); fileVo.setBucketName(s.name()); // 文件夹名称 fileVo.setFileName(g.get().objectName()); // 文件名称 fileVo.setUpdateTime(localDateTime2Date(g.get().lastModified().toLocalDateTime())); // 文件上传时间 Long size g.get().size(); if (size (1024 * 1024)) { fileVo.setFileSize(df.format(((double) size / 1024 / 1024)) MB); // 文件大小如果超过1M则把单位换成MB } else if (size 1024) { fileVo.setFileSize(df.format(((double) size / 1024)) KB); // 文件大小如果没超过1M但是超过1000字节则把单位换成KB } else { fileVo.setFileSize( size bytes); // // 文件大小如果没超过1000字节则把单位换成bytes } list.add(fileVo); } catch (ErrorResponseException e) { e.printStackTrace(); } catch (InsufficientDataException e) { e.printStackTrace(); } catch (InternalException e) { e.printStackTrace(); } catch (InvalidBucketNameException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (InvalidResponseException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (XmlParserException e) { e.printStackTrace(); } catch (ServerException e) { e.printStackTrace(); } }); } catch (XmlParserException e) { e.printStackTrace(); } }); } JSONObject res new JSONObject(); res.put(code, 200); res.put(message, 获取文件列表成功); // 按最后上传时间排序 list.sort(new ComparatorFileVo() { Override public int compare(FileVo o1, FileVo o2) { return o2.getUpdateTime().compareTo(o1.getUpdateTime()); } }); // 分页 List returnList PageUtil.startPage(list, pageNum, pageSize); res.put(list, returnList); ObjectMapper mapper new ObjectMapper(); String s mapper.writeValueAsString(res); return s; } private Date localDateTime2Date(LocalDateTime toLocalDateTime) { Date date Date.from( toLocalDateTime.atZone( ZoneId.systemDefault()).toInstant()); return date; } // ApiOperation(文件删除)文件删除 RequestMapping(value /delete, method RequestMethod.POST) ResponseBody public CommonResult delete(RequestParam(objectName) String objectName) { try { MinioClient minioClient MinioClient.builder() .endpoint(ENDPOINT) .credentials(ACCESS_KEY,SECRET_KEY) .build(); minioClient.removeObject(RemoveObjectArgs.builder().bucket(BUCKET_NAME).object(objectName).build()); return CommonResult.success(null); } catch (Exception e) { e.printStackTrace(); } return CommonResult.failed(); } }
业务类servicedao入库等操作请自行补充。
源码下载地址
global-fairy-top-pi4j: java语言读取dth11温湿度传感器参数通过接口对外提供
具体版本参考v0.3.1 打包部署 Idea中maven package项目之后拷贝jar包到云服务器 启动 nohup java -jar global-fairy-top-pi4j-0.0.1-SNAPSHOT.jar
测试 localhost:8082/minio/fileList 注意事项
常见问题 部署demo前请先安装mysql并配置好地址。