minio的javaAPI

章节快捷访问:

第一章:minio介绍与安装

https://blog.csdn.net/hzw2312/article/details/106077729

第二章:minio单机版,使用客户端备份文件

https://blog.csdn.net/hzw2312/article/details/106078150

第三章:minio的javaAPI

https://blog.csdn.net/hzw2312/article/details/106078390

第四章:minio的presigned URLs上传文件

https://blog.csdn.net/hzw2312/article/details/106078604

--------------------------------------------------


在之前我们已经把minio的服务端,客户端,以及镜像备份都做好了,现在我们来试试通过java的API来操作minio。

环境是Spring boot的

版本是2.1.4.RELEASE

参照官方的API文档:https://docs.min.io/cn/java-client-quickstart-guide.html

配置

首先我们先引入minio的maven配置:

<!--  minio配置  -->

<dependency>

    <groupId>io.minio</groupId>

    <artifactId>minio</artifactId>

    <version>3.0.10</version>

</dependency>

在配置一下minio的地址,用户名跟密码等:

minio:

  endpoint: http://192.168.51.78:9001

  accessKey: username

  secretKey: password

  # 下载地址

  http-url: http://127.0.0.1:8080/plat/admin_api/files/url

  imgSize: 10485760

  fileSize: 104857600

java代码

首先,先使用一个实体类接收minio的配置信息

import lombok.Data;

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.stereotype.Component;

/**

* 读取文件的配置

* @author 胡汉三

* @time 2020/5/12 10:14

*/

@Component

@Data

@ConfigurationProperties("minio")

public class FilesConfig {

    /**minio的路径**/

    private String endpoint;

    /**minio的accessKey**/

    private String accessKey;

    /**minio的secretKey**/

    private String secretKey;


    /**下载地址**/

    private String httpUrl;

    /**图片大小限制**/

    private Long imgSize;


    /**文件大小限制**/

    private Long fileSize;

}

接着再是写一个minio的操作模版类

import com.ktwlsoft.framework.files.config.FilesConfig;

import com.ktwlsoft.framework.files.vo.MinioItem;

import io.minio.MinioClient;

import io.minio.ObjectStat;

import io.minio.Result;

import io.minio.errors.*;

import io.minio.messages.Bucket;

import io.minio.messages.Item;

import lombok.RequiredArgsConstructor;

import lombok.SneakyThrows;

import org.springframework.beans.factory.InitializingBean;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;

import java.io.InputStream;

import java.security.InvalidKeyException;

import java.security.NoSuchAlgorithmException;

import java.util.ArrayList;

import java.util.List;

import java.util.Optional;

/**

* Minio模板类

* @author 胡汉三

* @time 2020/5/12 11:28

*/

@Component

@RequiredArgsConstructor

public class MinioTemplate implements InitializingBean {

    @Autowired

    private FilesConfig filesConfig;

    private MinioClient client;

    /**

    * 检查文件存储桶是否存在

    * @param bucketName

    * @return

    */

    @SneakyThrows

    public boolean bucketExists(String bucketName){

        return client.bucketExists(bucketName);

    }

    /**

    * 创建bucket

    *

    * @param bucketName bucket名称

    */

    @SneakyThrows

    public void createBucket(String bucketName) {

        if (!bucketExists(bucketName)) {

            client.makeBucket(bucketName);

        }

    }

    /**

    * 获取全部bucket

    * <p>

    * https://docs.minio.io/cn/java-client-api-reference.html#listBuckets

    */

    @SneakyThrows

    public List<Bucket> getAllBuckets() {

        return client.listBuckets();

    }

    /**

    * 根据bucketName获取信息

    * @param bucketName bucket名称

    */

    @SneakyThrows

    public Optional<Bucket> getBucket(String bucketName) {

        return client.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();

    }

    /**

    * 根据bucketName删除信息

    * @param bucketName bucket名称

    */

    @SneakyThrows

    public void removeBucket(String bucketName) {

        client.removeBucket(bucketName);

    }

    /**

    * 根据文件前缀查询文件

    *

    * @param bucketName bucket名称

    * @param prefix    前缀

    * @param recursive  是否递归查询

    * @return MinioItem 列表

    */

    @SneakyThrows

    public List<MinioItem> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {

        List<MinioItem> objectList = new ArrayList<>();

        Iterable<Result<Item>> objectsIterator = client.listObjects(bucketName, prefix, recursive);

        for (Result<Item> result : objectsIterator) {

            objectList.add(new MinioItem(result.get()));

        }

        return objectList;

    }

    /**

    * 获取文件外链

    *

    * @param bucketName bucket名称

    * @param objectName 文件名称

    * @param expires    过期时间 <=7

    * @return url

    */

    @SneakyThrows

    public String getObjectURL(String bucketName, String objectName, Integer expires) {

        return client.presignedGetObject(bucketName, objectName, expires);

    }

    /**

    * 获取文件外链

    *

    * @param bucketName bucket名称

    * @param objectName 文件名称

    * @return url

    */

    @SneakyThrows

    public String getObjectURL(String bucketName, String objectName) {

        return client.presignedGetObject(bucketName, objectName);

    }

    /**

    * 获取文件

    *

    * @param bucketName bucket名称

    * @param objectName 文件名称

    * @return 二进制流

    */

    @SneakyThrows

    public InputStream getObject(String bucketName, String objectName) {

        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-api-reference.html#removeObject

    */

    public void removeObject(String bucketName, String objectName) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException {

        client.removeObject(bucketName, objectName);

    }

    @Override

    public void afterPropertiesSet() throws Exception {

        this.client = new MinioClient(filesConfig.getEndpoint(), filesConfig.getAccessKey(), filesConfig.getSecretKey());

    }

}

MinioItem实体

import io.minio.messages.Item;

import io.minio.messages.Owner;

import io.swagger.annotations.ApiModelProperty;

import java.util.Date;

/**

* 文件对象

* @author 胡汉三

* @time 2019/8/29 14:53

*/

public class MinioItem {

    /**对象名称**/

    @ApiModelProperty("对象名称")

    private String objectName;

    /**最后操作时间**/

    @ApiModelProperty("最后操作时间")

    private Date lastModified;

    private String etag;

    /**对象大小**/

    @ApiModelProperty("对象大小")

    private String size;

    private String storageClass;

    private Owner owner;

    /**对象类型:directory(目录)或file(文件)**/

    @ApiModelProperty("对象类型:directory(目录)或file(文件)")

    private String type;

    public MinioItem(String objectName, Date lastModified, String etag, String size, String storageClass, Owner owner, String type) {

        this.objectName = objectName;

        this.lastModified = lastModified;

        this.etag = etag;

        this.size = size;

        this.storageClass = storageClass;

        this.owner = owner;

        this.type = type;

    }

    public MinioItem(Item item) {

        this.objectName = item.objectName();

        this.type = item.isDir() ? "directory" : "file";

        this.etag = item.etag();

        long sizeNum = item.objectSize();

        this.size = sizeNum > 0 ? convertFileSize(sizeNum):"0";

        this.storageClass = item.storageClass();

        this.owner = item.owner();

        try {

            this.lastModified = item.lastModified();

        }catch(NullPointerException e){}

    }

    public String getObjectName() {

        return objectName;

    }

    public void setObjectName(String objectName) {

        this.objectName = objectName;

    }

    public Date getLastModified() {

        return lastModified;

    }

    public void setLastModified(Date lastModified) {

        this.lastModified = lastModified;

    }

    public String getEtag() {

        return etag;

    }

    public void setEtag(String etag) {

        this.etag = etag;

    }

    public String getSize() {

        return size;

    }

    public void setSize(String size) {

        this.size = size;

    }

    public String getStorageClass() {

        return storageClass;

    }

    public void setStorageClass(String storageClass) {

        this.storageClass = storageClass;

    }

    public Owner getOwner() {

        return owner;

    }

    public void setOwner(Owner owner) {

        this.owner = owner;

    }

    public String getType() {

        return type;

    }

    public void setType(String type) {

        this.type = type;

    }

    public String convertFileSize(long size) {

        long kb = 1024;

        long mb = kb * 1024;

        long gb = mb * 1024;

        if (size >= gb) {

            return String.format("%.1f GB", (float) size / gb);

        } else if (size >= mb) {

            float f = (float) size / mb;

            return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);

        } else if (size >= kb) {

            float f = (float) size / kb;

            return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);

        } else{

            return String.format("%d B", size);

        }

    }

}

接下来写一个对外的http上传接口

import com.google.api.client.util.Lists;

import com.ktwlsoft.framework.files.config.FilesConfig;

import com.ktwlsoft.framework.files.service.impl.MinioTemplate;

import com.ktwlsoft.framework.files.util.BaseConstant;

import com.ktwlsoft.framework.files.util.BucketNameConfig;

import com.ktwlsoft.framework.files.vo.UpLoadResult;

import com.ktwlsoft.framework.common.MvcController;

import com.ktwlsoft.framework.common.result.ActionResult;

import com.ktwlsoft.framework.common.result.ResultCode;

import io.swagger.annotations.Api;

import io.swagger.annotations.ApiOperation;

import io.swagger.annotations.ApiParam;

import org.apache.commons.lang3.StringUtils;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.*;

import org.springframework.web.multipart.MultipartFile;

import java.util.List;

/**

* 文件上传

* @author 胡汉三

* @time 2020/5/12 12:37

*/

@Api(value = "文件上传", description = "文件上传接口", hidden = true)

@RestController

@RequestMapping(BaseConstant.PREFIX_AUTH+"/upload")

public class UploadFilesController extends MvcController {

    private Log log = LogFactory.getLog(UploadFilesController.class);

    @Autowired

    private MinioTemplate minioTemplate;

    @Autowired

    private FilesConfig config;

    /**

    * 上传文件

    * @param upfile        上传的文件对象

    * @param bucketName    所属的存储桶(第一级目录)

    * @param perfixName    文件对象前缀名称

    * @param expires      外链过期时间

    * @return

    */

    @ApiOperation(value = "上传文件" , response = UpLoadResult.class)

    @PostMapping("file")

    public ActionResult<Object> upload(@ApiParam(name = "upfile",value = "文件参数名称") @RequestParam("upfile") MultipartFile upfile,

                                            @ApiParam(name = "bucketName",value = "文件桶名称") String bucketName,

                                            @ApiParam(name = "perfixName",value = "文件对象前缀名称") String perfixName,

                                            @ApiParam(name = "expires",value = "链接过期时间") Integer expires,

                                            @ApiParam(name = "dateFile",value = "是否需要创建时间文件夹:1是,其它否") Integer dateFile) {

        String fileName = upfile.getOriginalFilename();

        try {

            fileCheck(upfile,fileName);

        } catch (Exception e) {

            return error(ResultCode.DATA_INPUT_ERROR.getValue(),e.getMessage());

        }

        if(StringUtils.isBlank(bucketName)){

            return error(ResultCode.DATA_INPUT_EMPTY);

        }

        if(StringUtils.isBlank(fileName)){

            return error(ResultCode.DATA_INPUT_EMPTY);

        }

        StringBuilder sbFile = new StringBuilder();

        if(StringUtils.isNotBlank(perfixName)){

            sbFile.append(perfixName).append(BucketNameConfig.FILE_SPLIT_PATH);

        }

        if(dateFile != null && dateFile == 1){

            // 创建时间文件夹

            sbFile.append(BucketNameConfig.getYear());

            sbFile.append(BucketNameConfig.FILE_SPLIT_PATH);

            sbFile.append(BucketNameConfig.getMonthAndDay());

            sbFile.append(BucketNameConfig.FILE_SPLIT_PATH);

        }

        sbFile.append(fileName);

        fileName = sbFile.toString();

        try {

            minioTemplate.createBucket(bucketName);

            minioTemplate.putObject(bucketName, fileName, upfile.getInputStream());

            UpLoadResult result = new UpLoadResult();

            if(expires == null){

                expires = BaseConstant.ONE_DAY;

            }

            result.setFileUrl(config.getHttpUrl()+"?bucketName="+bucketName+"&objectName="+fileName+"&expires="+expires);

            result.setBucketName(bucketName);

            result.setObjectName(fileName);

            return success(result);

        } catch (Exception e) {

            log.error("文件上传异常", e);

            ResultCode code =  ResultCode.FILE_SAVE_ERROR;

            return error(code);

        }

    }

    /**

    * 多上传文件

    * @param upfileList    上传的文件对象集合

    * @param bucketName    所属的存储桶(第一级目录)

    * @param expires      外链过期时间

    * @return

    */

    @ApiOperation(value = "多上传文件" , response = UpLoadResult.class)

    @PostMapping("fileList")

    public ActionResult<Object> uploadList(@ApiParam(name = "upfileList",value = "文件集合参数名称") @RequestParam("upfileList") List<MultipartFile> upfileList,

                                      @ApiParam(name = "bucketName",value = "文件桶名称") String bucketName,

                                          @ApiParam(name = "perfixName",value = "文件前缀名称") String perfixName,

                                      @ApiParam(name = "expires",value = "链接过期时间") Integer expires,

                                        @ApiParam(name = "dateFile",value = "是否需要创建时间文件夹:1是,其它否") Integer dateFile) {

        if(StringUtils.isBlank(bucketName)){

            return error(ResultCode.DATA_INPUT_EMPTY);

        }

        List<UpLoadResult> resultList = Lists.newArrayList();

        StringBuilder sbFile = new StringBuilder();

        if(StringUtils.isNotBlank(perfixName)){

            sbFile.append(perfixName).append(BucketNameConfig.FILE_SPLIT_PATH);

        }

        if(dateFile != null && dateFile == 1){

            // 创建时间文件夹

            sbFile.append(BucketNameConfig.getYear());

            sbFile.append(BucketNameConfig.FILE_SPLIT_PATH);

            sbFile.append(BucketNameConfig.getMonthAndDay());

            sbFile.append(BucketNameConfig.FILE_SPLIT_PATH);

        }

        for (MultipartFile file:upfileList) {

            String fileName = file.getOriginalFilename();

            try {

                fileCheck(file,fileName);

            } catch (Exception e) {

                return error(ResultCode.DATA_INPUT_ERROR.getValue(),e.getMessage());

            }

            fileName = sbFile.toString()+fileName;

            try {

                minioTemplate.createBucket(bucketName);

                minioTemplate.putObject(bucketName, fileName, file.getInputStream());

                UpLoadResult result = new UpLoadResult();

                if(expires == null){

                    expires = BaseConstant.ONE_DAY;

                }

                result.setFileUrl(config.getHttpUrl()+"?bucketName="+bucketName+"&objectName="+fileName+"&expires="+expires);

                result.setBucketName(bucketName);

                result.setObjectName(fileName);

                resultList.add(result);

            } catch (Exception e) {

                log.error("文件上传异常", e);

                ResultCode code =  ResultCode.FILE_SAVE_ERROR;

                return error(code);

            }

        }

        return success(resultList);

    }

    /**

    * 判断是否图片

    */

    private boolean isImage(String fileName) {

        //设置允许上传文件类型

        String suffixList = "jpg,gif,png,ico,bmp,jpeg";

        // 获取文件后缀

        String suffix = fileName.substring(fileName.lastIndexOf(".")

                + 1, fileName.length());

        if (suffixList.contains(suffix.trim().toLowerCase())) {

            return true;

        }

        return false;

    }

    /**

    * 验证文件大小

    * @param upfile

    * @param fileName  文件名称

    * @throws Exception

    */

    private void fileCheck(MultipartFile upfile,String fileName) throws Exception {

        Long size = upfile.getSize();

        if(isImage(fileName)){

            if(size > config.getImgSize()){

                throw new Exception("上传对图片大于:"+(config.getImgSize() / 1024 / 1024) +"M限制");

            }

        }else{

            if(size > config.getFileSize()){

                throw new Exception("上传对文件大于:"+(config.getFileSize() / 1024 / 1024) +"M限制");

            }

        }

    }

}

下载

大家可能会疑惑,这个httpUrl的配置是什么鬼,这个就是文件的下载地址了,因为我们上传了文件过后,总要返回一个下载地址回去给别人做存储。而且要永久有效的连接。但是minio有一个功能是生成可以设置过期时间的外链。所以我们这里就做一个中转,让应用来访问我们的接口,我们来调用minio生成可访问的链接。

有过期时间的外链

/**

* 获取文件外链

* @param bucketName        文件桶名称

* @param objectName        文件对象名称

* @param expires          外链有效时间(单位:秒)

* @return

*/

@ApiOperation(value = "获取文件外链", response = ActionResult.class)

@GetMapping("/url")

public ModelAndView getObjectUrl(@ApiParam(name = "bucketName",value = "文件桶名称")String bucketName,

                                @ApiParam(name = "objectName",value = "文件对象名称") String objectName,

                                @ApiParam(name = "bucketName",value = "外链有效时间(单位:秒)")Integer expires) throws IOException, XmlPullParserException, NoSuchAlgorithmException, InvalidKeyException, InvalidPortException, ErrorResponseException, NoResponseException, InvalidBucketNameException, InsufficientDataException, InvalidEndpointException, InternalException, InvalidExpiresRangeException {

    //ModelAndView model = new ModelAndView();

    if(StringUtils.isBlank(bucketName)){

        return null;

    }

    if(StringUtils.isBlank(objectName)){

        return null;

    }

    if(expires == null){

        expires = BaseConstant.ONE_DAY;

    }

    String utl = template.getObjectURL(bucketName, objectName, expires);

    if(StringUtils.isBlank(utl)){

        return null;

    }

    return  new ModelAndView(new RedirectView(utl));

}

永久有效的外链

我没有在java的API中找到可以设置永久有效的外链设置。但是可以在客户端中设置某个文件桶的内容的下载策略

mc policy public minio80/staticFile

意思就是设置minio80文件桶的staticFile文件桶为开放管理,可以通过url直接下载

【桶名称】/【路径】一路直接到要下载的文件

下载文件

/**

* 文件流下载

* @param bucketName    文件桶名称

* @param objectName    文件对象名称

* @param response

* @param request

*/

@ApiOperation(value = "文件流下载", response = ActionResult.class)

@GetMapping("/io/{bucketName}/{objectName}/")

public void downloadIo(@ApiParam(name = "bucketName",value = "文件桶名称") @PathVariable String bucketName,

                      @ApiParam(name = "objectName",value = "文件对象名称") @PathVariable String objectName, HttpServletResponse response, HttpServletRequest request){

    javax.servlet.ServletOutputStream out = null;

    try (InputStream inputStream = template.getObject(bucketName,objectName)) {

        response.setHeader("Content-Disposition", "attachment;filename=" + objectName.substring(objectName.lastIndexOf("/")+1));

        response.setContentType("application/force-download");

        response.setCharacterEncoding("UTF-8");

        out = response.getOutputStream();

        byte[] content = new byte[1024];

        int length = 0;

        while ((length = inputStream.read(content)) != -1) {

            out.write(content, 0, length);

        }

        out.flush();

    } catch (Exception e) {

        log.error("文件读取异常", e);

    }finally {

        if(out != null){

            try {

                out.close();

            } catch (IOException e) {

                log.error("文件流关闭异常", e);

            }

        }

    }

}

完整的控制器代码

import com.github.pagehelper.PageInfo;

import com.ktwlsoft.framework.files.service.impl.MinioTemplate;

import com.ktwlsoft.framework.files.util.BaseConstant;

import com.ktwlsoft.framework.files.vo.MinioItem;

import com.ktwlsoft.framework.common.MvcController;

import com.ktwlsoft.framework.common.result.ActionResult;

import com.ktwlsoft.framework.common.result.ResultCode;

import io.minio.errors.*;

import io.swagger.annotations.Api;

import io.swagger.annotations.ApiOperation;

import io.swagger.annotations.ApiParam;

import org.apache.commons.lang3.StringUtils;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.*;

import org.springframework.web.servlet.ModelAndView;

import org.springframework.web.servlet.view.RedirectView;

import org.xmlpull.v1.XmlPullParserException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.io.InputStream;

import java.security.InvalidKeyException;

import java.security.NoSuchAlgorithmException;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

/**

* 文件对象控制器

* @author 胡汉三

* @time 2020/5/12 14:49

*/

@Api(value = "文件对象操作", description = "文件对象操作接口", hidden = true)

@RestController

@RequestMapping(BaseConstant.PREFIX_AUTH+"/files")

public class FilesController extends MvcController {

    /**日志对象**/

    private Log log = LogFactory.getLog(FilesController.class);

    /**Minio模板类注入**/

    @Autowired

    private MinioTemplate template;

    /**

    * 根据文件前缀查询文件

    * @param bucketName    文件桶名称

    * @param objectName    文件对象名称

    * @return

    * @throws InvalidPortException

    * @throws InvalidEndpointException

    */

    @ApiOperation(value = "根据文件前缀查询文件", response = ActionResult.class)

    @GetMapping("/prefix/list")

    public ActionResult<Object> filterObject(@ApiParam(name = "bucketName",value = "文件桶名称")String bucketName,

                                            @ApiParam(name = "objectName",value = "文件对象名称")String objectName) throws InvalidPortException, InvalidEndpointException {

        if(StringUtils.isBlank(bucketName)){

            return error(ResultCode.DATA_INPUT_EMPTY.getValue(),"文件桶名称不能为空");

        }

        List<MinioItem> list = template.getAllObjectsByPrefix(bucketName, objectName, false);

        PageInfo<MinioItem> pageInfo = new PageInfo<>();

        pageInfo.setTotal(list.size());

        pageInfo.setPageSize(10000);

        pageInfo.setList(list);

        return success(pageInfo);

    }

    /**

    * 获取文件外链

    * @param bucketName        文件桶名称

    * @param objectName        文件对象名称

    * @param expires          外链有效时间(单位:秒)

    * @return

    */

    @ApiOperation(value = "获取文件外链", response = ActionResult.class)

    @GetMapping("/{bucketName}/{objectName}/{expires}/")

    public ActionResult<Object> getObject( @ApiParam(name = "bucketName",value = "文件桶名称") @PathVariable String bucketName,

                                          @ApiParam(name = "objectName",value = "文件对象名称") @PathVariable String objectName,

                                          @ApiParam(name = "bucketName",value = "外链有效时间(单位:秒)") @PathVariable Integer expires) throws IOException, XmlPullParserException, NoSuchAlgorithmException, InvalidKeyException, InvalidPortException, ErrorResponseException, NoResponseException, InvalidBucketNameException, InsufficientDataException, InvalidEndpointException, InternalException, InvalidExpiresRangeException {

        Map<String,Object> responseBody = new HashMap<>(4);

        // Put Object info

        responseBody.put("bucket" , bucketName);

        responseBody.put("object" , objectName);

        if(expires <= 0){

            expires = BaseConstant.ONE_DAY;

        }

        responseBody.put("url" , template.getObjectURL(bucketName, objectName, expires));

        responseBody.put("expires" ,  expires);

        return success(responseBody);

    }

    /**

    * 获取文件外链

    * @param bucketName        文件桶名称

    * @param objectName        文件对象名称

    * @param expires          外链有效时间(单位:秒)

    * @return

    */

    @ApiOperation(value = "获取文件外链", response = ActionResult.class)

    @GetMapping("/url")

    public ModelAndView getObjectUrl(@ApiParam(name = "bucketName",value = "文件桶名称")String bucketName,

                                    @ApiParam(name = "objectName",value = "文件对象名称") String objectName,

                                    @ApiParam(name = "bucketName",value = "外链有效时间(单位:秒)")Integer expires) throws IOException, XmlPullParserException, NoSuchAlgorithmException, InvalidKeyException, InvalidPortException, ErrorResponseException, NoResponseException, InvalidBucketNameException, InsufficientDataException, InvalidEndpointException, InternalException, InvalidExpiresRangeException {

        //ModelAndView model = new ModelAndView();

        if(StringUtils.isBlank(bucketName)){

            return null;

        }

        if(StringUtils.isBlank(objectName)){

            return null;

        }

        if(expires == null){

            expires = BaseConstant.ONE_DAY;

        }

        String utl = template.getObjectURL(bucketName, objectName, expires);

        if(StringUtils.isBlank(utl)){

            return null;

        }

        return  new ModelAndView(new RedirectView(utl));

    }

    /**

    * 文件流下载

    * @param bucketName    文件桶名称

    * @param objectName    文件对象名称

    * @param response

    * @param request

    */

    @ApiOperation(value = "文件流下载", response = ActionResult.class)

    @GetMapping("/io/{bucketName}/{objectName}/")

    public void downloadIo(@ApiParam(name = "bucketName",value = "文件桶名称") @PathVariable String bucketName,

                          @ApiParam(name = "objectName",value = "文件对象名称") @PathVariable String objectName, HttpServletResponse response, HttpServletRequest request){

        javax.servlet.ServletOutputStream out = null;

        try (InputStream inputStream = template.getObject(bucketName,objectName)) {

            response.setHeader("Content-Disposition", "attachment;filename=" + objectName.substring(objectName.lastIndexOf("/")+1));

            response.setContentType("application/force-download");

            response.setCharacterEncoding("UTF-8");

            out = response.getOutputStream();

            byte[] content = new byte[1024];

            int length = 0;

            while ((length = inputStream.read(content)) != -1) {

                out.write(content, 0, length);

            }

            out.flush();

        } catch (Exception e) {

            log.error("文件读取异常", e);

        }finally {

            if(out != null){

                try {

                    out.close();

                } catch (IOException e) {

                    log.error("文件流关闭异常", e);

                }

            }

        }

    }

    /**

    * 删除文件对象

    * @param bucketName    文件桶名称

    * @param objectName    文件对象名称:(pdf/2020/0510/test.pdf)

    */

    @ApiOperation(value = "删除文件对象", response = ActionResult.class)

    @DeleteMapping("/{bucketName}/{objectName}/")

    public ActionResult<Object> deleteObject(

            @ApiParam(name = "bucketName",value = "文件桶名称") @PathVariable String bucketName,

            @ApiParam(name = "objectName",value = "文件对象名称:(pdf/2020/0510/test.pdf)") @PathVariable String objectName)

            throws IOException, XmlPullParserException, NoSuchAlgorithmException, InvalidKeyException, InvalidPortException, ErrorResponseException, NoResponseException, InvalidBucketNameException, InsufficientDataException, InternalException{

        template.removeObject(bucketName, objectName);

        return success(null,"删除成功");

    }

}

-------------------------------------新增BucketNameConfig-------------------------------------------

import java.time.LocalDate;

import java.time.format.DateTimeFormatter;

import java.util.Date;

/**

* 文件夹(桶bucket)名称创建器

* @author 胡汉三

* @time 2019/8/29 11:50

*/

public class BucketNameConfig {

    /**minion文档目录分割符**/

    public static final String FILE_SPLIT_PATH = "/";

    /**时间格式化格式**/

    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");

    /**

    * 获得当前时间:年(格式:yyyy)

    * @return

    */

    public static int getYear(){

        return LocalDate.now().getYear();

    }

    /**

    * 获得当前时间:月(格式:MM)

    * @return

    */

    public static String getMonth(){

        int month = LocalDate.now().getMonth().getValue();

        if(month < 10){

            return "0"+month;

        }

        return Integer.valueOf(month).toString();

    }

    /**

    * 获得当前时间:日(格式:dd)

    * @return

    */

    public static String getDay(){

        int day = LocalDate.now().getDayOfMonth();

        if(day < 10){

            return "0"+day;

        }

        return Integer.valueOf(day).toString();

    }

    /**

    * 获得当前时间(格式:yyyyMMdd)

    * @return

    */

    public static String getFullDay(){

        return LocalDate.now().format(DATE_FORMATTER);

    }

    /**

    * 获得当前时间月和日(格式:MMdd)

    * @return

    */

    public static String getMonthAndDay(){

        return getMonth()+getDay();

    }

}


————————————————

版权声明:本文为CSDN博主「BUG胡汉三」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/hzw2312/article/details/106078390

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容