springboot整合minio洒闸,實現(xiàn)文件上傳與下載,且支持鏈接永久訪問

1掀宋、minio部署

1.1 拉取鏡像

docker pull minio/minio

1.2 創(chuàng)建數(shù)據(jù)目錄

mkdir -p /home/guanz/minio
mkdir -p /home/guanz/minio/midata

1.3 啟動minio

docker run -d -p 9000:9000 -p 9001:9001 --restart=always -e MINIO_ACCESS_KEY=guanz -e MINIO_SECRET_KEY=guanz@123 -v $PWD/midata:/data  minio/minio server /data --console-address "192.168.1.139:9001"

2、項目搭建

2.1 引入jar

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

2.2 application-dev.yml

spring
    minio:
    # Minio服務(wù)器地址
    endpoint: http://192.168.1.139:9000
    port: 9001
    create-bucket: true
    bucketName: push-test
    # Minio服務(wù)器賬號
    accessKey: guanz
    # Minio服務(wù)器密碼
    secretKey: guanz@123
    secure: false
    configDir: /home/push
    # 文件大小 單位M
    maxFileSize: 10
    expires: 604800

2.4 MinioConfig.java

package com.pavis.app.saasbacken.config;

import io.minio.MinioClient;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/**
 * @program: push-saas
 * @description:
 * @author: Guanzi
 * @created: 2021/11/02 13:47
 */
@Data
@Component
@ConfigurationProperties(prefix = "minio")
@Slf4j
@Configuration
public class MinioConfig {
    @ApiModelProperty("endPoint是一個URL唆途,域名肛搬,IPv4或者IPv6地址")
    @Value("${spring.minio.endpoint}")
    private String endpoint;

    @ApiModelProperty("TCP/IP端口號")
    @Value("${spring.minio.port}")
    private int port;

    @ApiModelProperty("accessKey類似于用戶ID温赔,用于唯一標(biāo)識你的賬戶")
    @Value("${spring.minio.accessKey}")
    private String accessKey;

    @ApiModelProperty("secretKey是你賬戶的密碼")
    @Value("${spring.minio.secretKey}")
    private String secretKey;

    @ApiModelProperty("如果是true啤贩,則用的是https而不是http,默認(rèn)值是true")
    @Value("${spring.minio.secure}")
    private Boolean secure;

    @ApiModelProperty("默認(rèn)存儲桶")
    @Value("${spring.minio.bucketName}")
    private String bucketName;

    @ApiModelProperty("配置目錄")
    @Value("${spring.minio.configDir}")
    private String configDir;

    @ApiModelProperty("文件大小")
    @Value("${spring.minio.maxFileSize}")
    private Integer maxFileSize;

    @ApiModelProperty("簽名有效時間")
    @Value("${spring.minio.expires}")
    private Integer expires;

    /**
     * 注入minio 客戶端
     * @return
     */
    @Bean
    public MinioClient minioClient(){
        log.info("endpoint:{},port:{},accessKey:{},secretKey:{},secure:{}",endpoint, port, accessKey, secretKey,secure);
        return MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
    }
}

3枉氮、文件上傳

3.1 關(guān)鍵代碼

MinioController.java
/**
     * 文件上傳
     * @param file
     * @return
     */
    @PostMapping("/upload")
    public Map<String, Object> upload(MultipartFile file){
        return minioService.upload(file);
    }
MinioServiceImpl.java
@Override
    public Map<String, Object> upload(MultipartFile file) {
        Map<String, Object> res = new HashMap<>();
        try {
            BucketExistsArgs bucketArgs = BucketExistsArgs.builder().bucket(bucketName).build();
            // todo 檢查bucket是否存在楼肪。
            boolean found = minioClient.bucketExists(bucketArgs);

            PutObjectArgs objectArgs = PutObjectArgs.builder().object(file.getOriginalFilename())
                    .bucket(bucketName)
                    .contentType(file.getContentType())
                    .stream(file.getInputStream(), file.getSize(), -1).build();

            ObjectWriteResponse objectWriteResponse = minioClient.putObject(objectArgs);
            System.out.println(objectWriteResponse.etag());
            res.put("code", "1");
            res.put("mess", "ok");
            return res;
        } catch (Exception e) {
            e.printStackTrace();
            log.info(e.getMessage());
        }
        res.put("code", "0");
        return res;
    }

4惹悄、文件下載

@Override
    public void download(String filename, HttpServletResponse res) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
        BucketExistsArgs bucketArgs = BucketExistsArgs.builder().bucket(bucketName).build();
        boolean bucketExists = minioClient.bucketExists(bucketArgs);
        log.info("bucketExists:{}", bucketExists);

        GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName)
                .object(filename).build();
        System.err.println("objectArgs:" + JSON.toJSONString(objectArgs));
        try (GetObjectResponse response = minioClient.getObject(objectArgs)) {
            System.err.println("response:" + JSON.toJSONString(response));
            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");// 設(shè)置強(qiáng)制下載不打開
                res.addHeader("Content-Disposition", "attachment;fileName=" + filename);
                try (ServletOutputStream stream = res.getOutputStream()) {
                    stream.write(bytes);
                    stream.flush();
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
}
下載地址:
image.png

5、文件永久鏈接下載

5.1 配置

image.png

5.2 關(guān)鍵代碼

/**
    * 生成一個GET請求的分享鏈接价匠。
    * 失效時間默認(rèn)是7天央星。
    *
    * @param bucketName 存儲桶名稱
    * @param objectName 存儲桶里的對象名稱
    * @param expires    失效時間(以秒為單位)惫东,默認(rèn)是7天,不得大于七天
    * @return
    */
   public String presignedGetObject(String bucketName, String objectName, Integer expires) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
       BucketExistsArgs bucketArgs = BucketExistsArgs.builder().bucket(bucketName).build();
       boolean bucketExists = minioClient.bucketExists(bucketArgs);
       // boolean flag = bucketExists(bucketName);
       String url = "";
       if (bucketExists) {
           try {
               if (expires == null){
                   expires = 604800;
               }

               GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder()
                       .method(Method.GET)
                       .bucket(bucketName)
                       .object(objectName)
                       // .expiry(expires)
                       .build();
               url = minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs);
               log.info("*******url2:{}",url);
           } catch (Exception e) {
               log.info("presigned get object fail:{}",e);
           }
       }
       return url;
   }
下載地址:
http://192.168.1.139:9000/push-test/qiyeku.jpg
至此颓遏,springboot+minio 結(jié)束滞时。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末坪稽,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子黍判,更是在濱河造成了極大的恐慌篙梢,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贬墩,死亡現(xiàn)場離奇詭異妄呕,居然都是意外死亡陶舞,警方通過查閱死者的電腦和手機(jī)绪励,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門优炬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蠢护,你說我怎么就攤上這事】叮” “怎么了贯吓?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵悄谐,是天一觀的道長库北。 經(jīng)常有香客問我爬舰,道長寒瓦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任垃你,我火速辦了婚禮喂很,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘少辣。我一直安慰自己,他們只是感情好望伦,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布煎殷。 她就那樣靜靜地躺著,像睡著了一般豪直。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上末融,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天暇韧,我揣著相機(jī)與錄音,去河邊找鬼懈玻。 笑死,一個胖子當(dāng)著我的面吹牛艺栈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播湿右,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吭狡!你這毒婦竟也來了堰塌?” 一聲冷哼從身側(cè)響起分衫,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蚪战,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞎疼,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡壁畸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了太抓。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡走敌,死狀恐怖逗噩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情异雁,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布残邀,位于F島的核電站,受9級特大地震影響芥挣,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜空另,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一蹋砚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧坝咐,春花似錦、人聲如沸墨坚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽帽撑。三九已至,卻和暖如春扣蜻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背莽使。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工磷蛹, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人味咳。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像责嚷,于是被迫代替她去往敵國和親掂铐。 傳聞我的和親對象是個殘疾皇子罕拂,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容