Minio的安裝&springBoot整合Minio進(jìn)行上傳下載代碼案例

Minio簡介

Minio是Apache License v2.0下發(fā)布的對象存儲服務(wù)器馁启。它與Amazon S3云存儲服務(wù)兼容芍秆。它最適合存儲非結(jié)構(gòu)化數(shù)據(jù),如照片霉颠,視頻蒿偎,日志文件怀读,備份和容器/ VM映像。對象的大小可以從幾KB到最大5TB
Minio服務(wù)器足夠輕苍糠,可以與應(yīng)用程序堆棧捆綁在一起啤誊,類似于NodeJS蚊锹,Redis和MySQL。

Minio Docker安裝

1. docker search minio --查找鏡像
2. docker pull minio/minio --安裝鏡像
3. docker run -p 9018:9000 --name minio1 
  -e "MINIO_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE" 
  -e "MINIO_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" 
  -v /mnt/data:/data 
  -v /mnt/config:/root/.minio 
  minio/minio server /data
4.docker logs 容器Id --查看minio賬號密碼
image-20200804152628168.png

**注:Minio的安裝具體步驟可以看這篇:http://www.reibang.com/p/68ac0477291d (推薦)
或者是 https://blog.csdn.net/L531003231/article/details/102969890?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param
**

Minio 整合SpringBoot 案例

ps:下面代碼出現(xiàn)的salt 是我自己創(chuàng)建的bucket

  1. Minio相關(guān)依賴
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.7</version>
        </dependency>
 <!-- https://mvnrepository.com/artifact/io.minio/minio -->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>6.0.11</version>
        </dependency>
     <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
  1. 配置文件增加Minio相關(guān)配置
minio:
  endpoint: 自己的minio地址
  accesskey: 賬號
  secretkey: 密碼

3.Minio實(shí)體類

@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class MinioProp {
    /**
    連接地址
     */
    private String endpoint;
    /**
     * 用戶名
     */
    private String accesskey;
    /**
     * 密碼
     */
    private String secretkey;
}
  1. Minio配置類
@Configuration
@EnableConfigurationProperties(MinioProp.class)
public class MinioConfig {

    @Autowired
    private MinioProp minioProp;

    /**
     * 獲取MinioClient
     */
    @Bean
    public MinioClient minioClient() throws InvalidPortException, InvalidEndpointException {
        return new MinioClient(minioProp.getEndpoint(),minioProp.getAccesskey(),minioProp.getSecretkey());
    }

}

5.Minio工具類(查詢bucket/上傳文件/獲取文件/刪除文件...)

@Component
public class MinioUtils {

    @Autowired
    private MinioProp minioProp;

    @Autowired
    private MinioClient client;

    /**
     * 創(chuàng)建bucket
     */
    public void createBucket(String bucketName) throws Exception{
        if (!client.bucketExists(bucketName)) {
            client.makeBucket(bucketName);
        }
    }

    /**
     * 上傳文件
     */
    public JSONObject uploadFile(MultipartFile file,String bucketName) throws Exception{
        JSONObject res = new JSONObject();
        res.put("code",0);
        //判斷文件是否為空
        if (null == file || 0 == file.getSize()) {
            res.put("msg","上傳文件不能為空");
            return res;
        }
        //判斷存儲桶是否存在  不存在則創(chuàng)建
        createBucket(bucketName);
        //文件名
        String originalFilename = file.getOriginalFilename();
        //新的文件名 = 存儲桶文件名_時間戳.后綴名
        String filelName = bucketName + "_" +
                System.currentTimeMillis() +
                originalFilename.substring(originalFilename.lastIndexOf("."));
        //開始上傳
        client.putObject(bucketName,filelName,file.getInputStream(),file.getContentType());
        res.put("code",1);
        res.put("msg",minioProp.getEndpoint() + "/" + bucketName + "/" + filelName);
        return res;
    }

    /**
     * 獲取全部bucket
     */
    public List<Bucket> getAllBuckets() throws Exception{
        return client.listBuckets();
    }

    /**
     * 根據(jù)bucketName獲取信息
     *
     * @param bucketName bucket名稱
     */
    public Optional<Bucket> getBucket(String bucketName) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidResponseException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {
        return client.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
    }

    /**
     * 根據(jù)bucketName刪除信息
     *
     * @param bucketName bucket名稱
     */
    public void removeBucket(String bucketName) throws Exception{
        client.removeBucket(bucketName);
    }
    /**
     * 獲取?件外鏈
     *
     * @param bucketName bucket名稱
     * @param objectName ?件名稱
     * @param expires 過期時間 <=7
     * @return url
     */
    public String getObjectURL(String bucketName, String objectName, Integer expires) throws Exception{
        return client.presignedGetObject(bucketName, objectName, expires);
    }
    /**
     * 獲取?件
     *
     * @param bucketName bucket名稱
     * @param objectName ?件名稱
     * @return ?進(jìn)制流
     */
    public InputStream getObject(String bucketName, String objectName) throws Exception{
        return client.getObject(bucketName, objectName);
    }
    /**
     * 上傳?件
     *
     * @param bucketName bucket名稱
     * @param objectName ?件名稱
     * @param stream ?件流
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
     */
    public void putObject(String bucketName, String objectName, InputStream stream) throws
            Exception {
        client.putObject(bucketName, objectName, stream, stream.available(),
                "application/octet-stream");
    }
    /**
     * 上傳?件
     *
     * @param bucketName bucket名稱
     * @param objectName ?件名稱
     * @param stream ?件流
     * @param size ??
     * @param contextType 類型
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
     */
    public void putObject(String bucketName, String objectName, InputStream stream, long
            size, String contextType) throws Exception {
        client.putObject(bucketName, objectName, stream, size, contextType);
    }
    /**
     * 獲取?件信息
     *
     * @param bucketName bucket名稱
     * @param objectName ?件名稱
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject
     */
    public ObjectStat getObjectInfo(String bucketName, String objectName) throws Exception
    {
        return client.statObject(bucketName, objectName);
    }
    /**
     * 刪除?件
     *
     * @param bucketName bucket名稱
     * @param objectName ?件名稱
     * @throws Exception https://docs.minio.io/cn/java-client-apireference.html#removeObject
     */
    public void removeObject(String bucketName, String objectName) throws Exception {
        client.removeObject(bucketName, objectName);
    }
}

6.Controller類

@Controller
public class MinioController {

    @Autowired
    private MinioUtils minioUtils;

    /**
     * 初始化頁面
     */
    @GetMapping("init")
    public String init(){
        return "file";
    }

    /**
     * 上傳文件
     */

    @PostMapping("/upload")
    public void upload(@RequestParam(name = "file",required = false)MultipartFile file){
        JSONObject res = null;
        try {
            res = minioUtils.uploadFile(file,"salt");
        }catch (Exception e){
            e.printStackTrace();
            res.put("code",0);
            res.put("msg","上傳失敗" + e.getMessage());
        }
        System.out.println(res.toString());
    }

    /**
     * 刪除文件
     * @param objectName
     * @throws Exception
     */
    @RequestMapping("/delete/{objectName}")
    public void delete(@PathVariable("objectName") String objectName) throws Exception{
        minioUtils.removeObject("salt",objectName);
        System.out.println("刪除成功");
    }

    /**
     * 下載文件到本地
     * @param objectName
     * @param response
     * @return
     * @throws Exception
     */
    @GetMapping("/download/{objectName}")
    public ResponseEntity download2(@PathVariable("objectName") String objectName, HttpServletResponse response) throws Exception{
        ResponseEntity<byte[]> responseEntity = null;
        InputStream stream = null;
        ByteArrayOutputStream output = null;
        try {
            // 獲取"myobject"的輸入流捷沸。
            stream = minioUtils.getObject("salt", objectName);
            if (stream == null) {
                System.out.println("文件不存在");
            }
            //用于轉(zhuǎn)換byte
            output = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            int n = 0;
            while (-1 != (n = stream.read(buffer))) {
                output.write(buffer, 0, n);
            }
            byte[] bytes = output.toByteArray();

            //設(shè)置header
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("Accept-Ranges", "bytes");
            httpHeaders.add("Content-Length", bytes.length + "");
//            objectName = new String(objectName.getBytes("UTF-8"), "ISO8859-1");
            //把文件名按UTF-8取出并按ISO8859-1編碼痒给,保證彈出窗口中的文件名中文不亂碼苍柏,中文不要太多,最多支持17個中文试吁,因?yàn)閔eader有150個字節(jié)限制。
            httpHeaders.add("Content-disposition", "attachment; filename=" + objectName);
            httpHeaders.add("Content-Type", "text/plain;charset=utf-8");
//            httpHeaders.add("Content-Type", "image/jpeg");
            responseEntity = new ResponseEntity<byte[]>(bytes, httpHeaders, HttpStatus.CREATED);

        } catch (MinioException e) {
            e.printStackTrace();
        } finally {
            if (stream != null) {
                stream.close();
            }
            if (output != null) {
                output.close();
            }
        }
        return responseEntity;
    }

    /**
     * 在瀏覽器預(yù)覽圖片
     * @param objectName
     * @param response
     * @throws Exception
     */
    @RequestMapping("/preViewPicture/{objectName}")
    public void download1(@PathVariable("objectName") String objectName, HttpServletResponse response) throws Exception{
        response.setContentType("image/jpeg");
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
            InputStream stream = minioUtils.getObject("salt",objectName);
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            int n = 0;
            while (-1 != (n = stream.read(buffer))) {
                output.write(buffer, 0, n);
            }
            byte[] bytes = output.toByteArray();
            out.write(bytes == null ? new byte[0]:bytes);
            out.flush();
        }finally {
            if (out != null) {
                out.close();
            }
        }
    }
}

  1. 簡單頁面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>測試minio上傳</title>
</head>
<body>
<form th:action="@{/upload}" accept-charset="UTF-8" method="post" enctype="multipart/form-data" target="_blank">
    文件:<input type="file" name="file">
    <input type="submit" value="上傳">
</form>

</body>
</html>

前面工具類可以參考:https://www.bilibili.com/read/cv6014961
經(jīng)過測試余耽,上傳,刪除碟贾,下載都已實(shí)現(xiàn)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末缕陕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子怜浅,更是在濱河造成了極大的恐慌蔬崩,老刑警劉巖沥阳,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異脉让,居然都是意外死亡功炮,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門滚澜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來设捐,“玉大人,你說我怎么就攤上這事蚂斤〖春” “怎么了召噩?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵具滴,是天一觀的道長。 經(jīng)常有香客問我构韵,道長疲恢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任棚愤,我火速辦了婚禮杂数,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘次和。我一直安慰自己那伐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著燃少,像睡著了一般。 火紅的嫁衣襯著肌膚如雪碍遍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天揣炕,我揣著相機(jī)與錄音东跪,去河邊找鬼虽填。 笑死,一個胖子當(dāng)著我的面吹牛斋日,可吹牛的內(nèi)容都是我干的恶守。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼庸毫,長吁一口氣:“原來是場噩夢啊……” “哼衫樊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起盒揉,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤兑徘,失蹤者是張志新(化名)和其女友劉穎挂脑,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肋联,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡刁俭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了虑粥。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宪哩。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡锁孟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出品抽,到底是詐尸還是另有隱情储笑,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布桑包,位于F島的核電站南蓬,受9級特大地震影響纺非,放射性物質(zhì)發(fā)生泄漏哑了。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一烧颖、第九天 我趴在偏房一處隱蔽的房頂上張望弱左。 院中可真熱鬧,春花似錦炕淮、人聲如沸拆火。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至润歉,卻和暖如春模狭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背踩衩。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工嚼鹉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人驱富。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓锚赤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親褐鸥。 傳聞我的和親對象是個殘疾皇子线脚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345