代码编织梦想

minio部署启用

参考官方,根据不同的操作系统,按照步骤部署

minio官网地址https://www.minio.org.cn/docs/minio/windows/index.html

 minio权限添加

minio权限添加https://blog.csdn.net/xnian_/article/details/130841657

windows环境部署

  1. 安装最小IO服务器

    从以下 URL 下载 MinIO 可执行文件:cmd 复制下面的下载

    https://dl.min.io/server/minio/release/windows-amd64/minio.exe

    下一步包括运行可执行文件的说明。 不能从资源管理器或通过双击文件来运行可执行文件。 相反,您调用可执行文件来启动服务器。

  2. 启动

    在 PowerShell 或命令提示符下,导航到可执行文件的位置或将文件的路径添加到系统。minio.exe$PATH

    使用此命令在文件夹中启动本地 MinIO 实例。 您可以替换为本地计算机上的另一个驱动器或文件夹路径。d:\minio d:\minio (自己下载的目录)

    .\minio.exe server d:\minio --console-address :9090

    该过程将其输出打印到系统控制台,类似于以下内容:

  3. 这个页面不能关闭,关闭后客户端无法访问,http://127.0.0.1:9000

                 初始的登录账号:

                RootUser: minioadmin
                RootPass: minioadmin

API: http://192.0.2.10:9000  http://127.0.0.1:9000
RootUser: minioadmin
RootPass: minioadmin

Console: http://192.0.2.10:9090 http://127.0.0.1:9090
RootUser: minioadmin
RootPass: minioadmin

Command-line: https://min.io/docs/minio/linux/reference/minio-mc.html
   $ mc alias set myminio http://192.0.2.10:9000 minioadmin minioadmin

Documentation: https://min.io/docs/minio/linux/index.html

WARNING: Detected default credentials 'minioadmin:minioadmin', we recommend tha

linux部署

创建自己的minio目录

mkdir minio

1远程拉取:

wget https://dl.min.io/server/minio/release/linux-amd64/minio

安装minio

2 文件赋权

给minio二进制文件赋权限,否则无法执行:

chmod +x minio

3启动minio

MINIO_ACCESS_KEY=minioadmin MINIO_SECRET_KEY=minioadmin nohup ./minio server --console-address ":9000" --address ":9001"  /data/ > /minio.log 2>&1 &

./minio server --console-address ":9000" --address ":9001"  /data/ > ./minio.log 2>&1 &

浏览器访问服务器minio,地址ip:9000,默认账号minioadmin 密码minioadmin

需要关闭防火墙linux防火墙操作命令https://blog.csdn.net/xnian_/article/details/130847602

java 代码整合

pom.xm

 <dependency>
     <groupId>io.minio</groupId>
     <artifactId>minio</artifactId>
     <version>7.1.0</version>
</dependency>

 配置文件.yml

minio:
  access-key: minio用户名
  secret-key: minio密码
  bucket-name: 桶名
  endpoint: minio地址

1. controller

package com.setsail.setsailcusserver.controller;

import com.alibaba.fastjson.JSONObject;
import com.setsail.setsailcusserver.entity.UserLoginAccEntity;
import com.setsail.setsailcusserver.service.UserRegisService;
import com.setsail.setsailcusserver.uatils.MinioUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.annotation.sql.DataSourceDefinition;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.Result;
import java.util.List;

/**
 * @Description:
 * @Title: UserRegisController
 * @Author hello
 * @Date: 2023/4/10 9:49
 * @Version 1.0
 */
@Slf4j
@RestController
@RequestMapping("/regis")
public class UserRegisController {
    @Resource
    private UserRegisService userRegisService;
    @Resource
    private MinioUtils minioUtils;


    /**
     * 上传
     * @param multipart
     * @throws Exception
     */
    @RequestMapping("uploadFile")
    public void uploadFile(@RequestBody JSONObject multipart) throws Exception{

            minioUtils.uploadFile(multipart);
    }

    /**
     * 删除
     * @param fileName
     * @throws Exception
     */
    @GetMapping("deleteObject")
    public void deleteObject(@RequestParam String  fileName) throws Exception{
        minioUtils.deleteObject(fileName);
    }

    /**
     * 下载
     *  reakFileName 需要带后缀名
     * @param response
     * @throws Exception
     */
    @GetMapping("downLoad")
    public void downLoad(HttpServletRequest request, HttpServletResponse response) throws Exception{
        minioUtils.downLoad("file_7355b51d-2a1a-4fc9-83b2-f6066dfd329d.png","cccc.jpg",response,request);
    }

    /**
     * 下载图片
     *  reakFileName 需要带后缀名
     * @param response
     * @throws Exception
     */
    @GetMapping("downloadImg")
    public void downloadImg( HttpServletResponse response) throws Exception{
        minioUtils.downloadImg("file_7355b51d-2a1a-4fc9-83b2-f6066dfd329d.png","imggsss.jpg",response);
    }

    /**
     *查看图片
     * @param response
     * @throws Exception
     */
    @GetMapping("getImage")
    public void getImage( HttpServletResponse response) throws Exception{
        minioUtils.getImage("file_7355b51d-2a1a-4fc9-83b2-f6066dfd329d.png",response);
    }

     /**
     * 获取权限策略
     * @param
     * @throws Exception
     */
    @GetMapping("getStrategy")
    public void getStrategy() throws Exception{
        minioUtils.getStrategy();
    }
}

2.MinioConfig

package com.setsail.setsailcusserver.config;

import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description:
 * @Title: MinioConfig
 * @Author hello
 * @Date: 2023/5/23 15:42
 * @Version 1.0
 */

@Configuration
public class MinioConfig {

    @Value("${minio.endpoint}")
    private String endpoint;
    @Value("${minio.access-key}")
    private String accesskey;
    @Value("${minio.secret-key}")
    private String secretKey;
    @Bean
    public MinioClient minioClient(){
        MinioClient minioClient = MinioClient.builder().endpoint(endpoint).
                credentials(accesskey, secretKey).region("china").build();
        return minioClient;
    }
}

3.MinioUtils工具类

package com.setsail.setsailcusserver.uatils;

/**
 * @Description:
 * @Title: MinioUtil
 * @Author hello
 * @Date: 2023/5/23 15:41
 * @Version 1.0
 */

import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.util.UuidUtils;
import com.setsail.setsailcusserver.config.MinioConfig;
import io.minio.*;
import io.minio.errors.MinioException;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import sun.nio.ch.IOUtil;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * @Author smallhou
 * @Date 2022-08-15 14:31
 * @Version V1.0
 */
@Slf4j
@Component
public class MinioUtils {

    @Autowired
    private MinioClient minioClient;

    @Value("${minio.bucket-name}")
    private String bucketName="file";
    /**
     * @Author smallhou
     * @Description //TODO 判断桶存在不存在,不存在创建桶
     * @Date 10:49 2022-08-16
     * @Param [bucketName]
     * @return void
     **/
    @SneakyThrows
    public void createBucket(String bucketName) {
        if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }

    }

    @SneakyThrows
    public InputStream getObjectInputStream(String objectName,String bucketName){
        GetObjectArgs getObjectArgs = GetObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .build();
        return minioClient.getObject(getObjectArgs);
    }


    public JSONObject uploadFile(JSONObject fileObj) throws Exception {
        JSONObject res = new JSONObject();
        res.put("code", 0);
        // 判断上传文件是否为空
        if (null == fileObj ) {
            res.put("msg", "上传文件不能为空");
            return res;
        }
        InputStream is=null;
        try {
            // 判断存储桶是否存在
            createBucket(bucketName);
            // 文件名
            String originalFilename = fileObj.getString("originalFilename");
            // 新的文件名 = 存储桶名称_时间戳.后缀名
            String fileName = bucketName + "_" + UuidUtils.generateUuid() + originalFilename.substring(originalFilename.lastIndexOf("."));
            // 开始上传 文件的绝对路径
            is=new FileInputStream(fileObj.getString("inputStream"));
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .contentType(fileObj.getString("contentType"))
                    .stream(is, is.available(), -1)
                    .build();
            this.minioClient.putObject(putObjectArgs);

            res.put("code", 1);
            res.put("msg",  bucketName + "/" + fileName);
            res.put("bucket", bucketName);
            res.put("fileName", fileName);
            return res;
        }  catch (Exception e) {
            e.printStackTrace();
            log.error("上传文件失败:{}", e.getMessage());
        }finally {
            is.close();
        }
        res.put("msg", "上传失败");
        return res;
    }

    public void downLoad(String fileName,String realFileName, HttpServletResponse response, HttpServletRequest request) {
        InputStream is=null;
        OutputStream os =null;
        try {
            is=getObjectInputStream(fileName,bucketName);
            if(is!=null){
                byte buf[] = new byte[1024];
                int length = 0;
                String codedfilename = "";
                String agent = request.getHeader("USER-AGENT");
                System.out.println("agent:" + agent);
                if ((null != agent && -1 != agent.indexOf("MSIE")) || (null != agent && -1 != agent.indexOf("Trident"))) {
                    String name = URLEncoder.encode(realFileName, "UTF8");
                    codedfilename = name;
                } else if (null != agent && -1 != agent.indexOf("Mozilla")) {
                    codedfilename = new String(realFileName.getBytes("UTF-8"), "iso-8859-1");
                } else {
                    codedfilename = new String(realFileName.getBytes("UTF-8"), "iso-8859-1");
                }
                response.reset();
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(realFileName.substring(realFileName.lastIndexOf("/") + 1), "UTF-8"));
                response.setContentType("application/x-msdownload");
                response.setCharacterEncoding("UTF-8");
                os = response.getOutputStream();
                // 输出文件
                while ((length = is.read(buf)) > 0) {
                    os.write(buf, 0, length);
                }
                // 关闭输出流
                os.close();

            }else{
                log.error("下载失败");
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error("错误:"+e.getMessage());
        }finally {
            if(is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void downloadImg(String filename,String realFileName, HttpServletResponse httpResponse) {

        try{
            //imgBucket--桶名称  filename-- 图片名称
            InputStream files = minioClient.getObject(bucketName, filename);
            InputStream ism = new BufferedInputStream(files);
            // 调用statObject()来判断对象是否存在。
            // 如果不存在, statObject()抛出异常,
            // 否则则代表对象存在
            minioClient.statObject(bucketName, filename);
            byte buf[] = new byte[1024];
            int length = 0;
            httpResponse.reset();
            //Content-disposition 是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件。
            // Content-disposition其实可以控制用户请求所得的内容存为一个文件的时候提供一个默认的文件名,
            // 文件直接在浏览器上显示或者在访问时弹出文件下载对话框。
            httpResponse.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(realFileName, "UTF-8"));
            httpResponse.setContentType("application/x-msdownload");
            httpResponse.setCharacterEncoding("utf-8");
            OutputStream osm = new BufferedOutputStream(httpResponse.getOutputStream());
            while ((length = ism.read(buf))>0) {
                osm.write(buf,0, length);
            }
            //关闭流
            osm.close();
        } catch (MinioException ex) {
            ex.printStackTrace();
        }  catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     *  图片查看
     * @param fileName
     * @param response
     * @throws IOException
     */
    public void getImage( String fileName, HttpServletResponse response) throws IOException {
        InputStream in = null;
        try {
            in = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .build()
            );
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (in == null){
            response.sendError(404, "未能找到图片");
        }


        //图片类型
        String[] fileArr = fileName.split("\\.");
        String contentType = "";
        StringBuilder originalFileName = new StringBuilder();
        if (fileArr.length > 1){
            contentType = "image/" + fileArr[fileArr.length - 1];
            for (int i = 0; i < fileArr.length - 1; i++) {
                originalFileName.append(fileArr[i]);
                if (i != fileArr.length - 2){
                    originalFileName.append(".");
                }
            }
        }else {
            contentType = "application/octet-stream";
            originalFileName = new StringBuilder(fileName);
        }

        try {
            response.addHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
            response.addHeader("X-Original-File-Name", originalFileName.toString());
            response.setContentType(contentType);
            ServletOutputStream outputStream = response.getOutputStream();
            IOUtils.copy(in, outputStream);
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void deleteObject(String fileName) {
        try {
            RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .build();
            minioClient.removeObject(removeObjectArgs);
        }catch (Exception e){
            log.error("错误:"+e.getMessage());
        }
    }


  public void getStrategy() {
        try {
            String bucketPolicy =                     
    
    
  minioClient.getBucketPolicy(GetBucketPolicyArgs.builder().bucket(bucketName).build());
            System.out.println(bucketPolicy);
            
        }catch (Exception e){
            log.error("错误:"+e.getMessage());
        }
    }
}

权限策略打印结果

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Principal": {
				"AWS": [
					"*"
				]
			},
			"Action": [
				"s3:GetBucketLocation",
				"s3:ListBucket",
				"s3:ListBucketMultipartUploads"
			],
			"Resource": [
				"arn:aws:s3:::file"
			]
		},
		{
			"Effect": "Allow",
			"Principal": {
				"AWS": [
					"*"
				]
			},
			"Action": [
				"s3:GetObject",
				"s3:ListMultipartUploadParts",
				"s3:PutObject",
				"s3:AbortMultipartUpload",
				"s3:DeleteObject"
			],
			"Resource": [
				"arn:aws:s3:::file/tess*",
				"arn:aws:s3:::file/*"
			]
		},
		{
			"Effect": "Allow",
			"Principal": {
				"AWS": [
					"*"
				]
			},
			"Action": [
				"s3:ListBucket"
			],
			"Resource": [
				"arn:aws:s3:::file"
			],
			"Condition": {
				"StringEquals": {
					"s3:prefix": [
						"tess"
					]
				}
			}
		}
	]
}

可以直接将保存图片的地址返回前端,通过地址直接支持查看图片,不需要调用后台代码

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xnian_/article/details/130841843