MinIO的上传和下载

我们经常接触到的关于minio的上传下载都是在项目中导入minio依赖,然后给配置一个MinioConfig,配置minio服务的地址账号密码等,如下图。

一、根据minio依赖实现上传下载

1.导入依赖

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

2.application.yml 配置信息

minio:
  endpoint: http://127.0.0.1:19000 #Minio服务所在地址
  bucketName: test-01 #存储桶名称
  accessKey: minioadmin #访问的key
  secretKey: minioadmin111 #访问的秘钥

 3.MinioConfig.class配置类

@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {

    private String endpoint;
    private String accessKey;
    private String secretKey;
    private String bucketName;

    @Bean
    public MinioClient minioClient() {
        return MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
    }
}

4.minio工具类


@Component
@Slf4j
public class MinioUtil {
    @Autowired
    private MinioConfig prop;

    @Resource
    private MinioClient minioClient;
    @Autowired
    private CodeService codeService;

    /**
     * 查看存储bucket是否存在
     * @return boolean
     */
    public Boolean bucketExists(String bucketName) {
        Boolean found;
        try {
            found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return found;
    }

    /**
     * 创建存储bucket
     * @return Boolean
     */
    public Boolean makeBucket(String bucketName) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
    /**
     * 删除存储bucket
     * @return Boolean
     */
    public Boolean removeBucket(String bucketName) {
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
    /**
     * 获取全部bucket
     */
    public List<Bucket> getAllBuckets() {
        try {
            List<Bucket> buckets = minioClient.listBuckets();
            return buckets;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }



    /**
     * 文件上传
     *
     * @param file 文件
     * @return Boolean
     */
    public String upload(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        if (StringUtils.isBlank(originalFilename)){
            throw new RuntimeException();
        }
        String fileName = UuidUtils.generateUuid() + originalFilename.substring(originalFilename.lastIndexOf("."));
        String objectName = CommUtils.getNowDateLongStr("yyyy-MM/dd") + "/" + fileName;
        try {
            PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(prop.getBucketName()).object(objectName)
                    .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
            //文件名称相同会覆盖
            minioClient.putObject(objectArgs);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return objectName;
    }

    /**
     * 预览图片
     * @param fileName
     * @return
     */
    public String preview(String fileName){
        // 查看文件地址
        GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(prop.getBucketName()).object(fileName).method(Method.GET).build();
        try {
            String url = minioClient.getPresignedObjectUrl(build);
            return url;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 文件下载
     * @param fileName 文件名称
     * @param res response
     * @return Boolean
     */
    public void download(String fileName, HttpServletResponse res) {
        GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(prop.getBucketName())
                .object(fileName).build();
        try (GetObjectResponse response = minioClient.getObject(objectArgs)){
            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");
                res.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
                try (ServletOutputStream stream = res.getOutputStream()){
                    stream.write(bytes);
                    stream.flush();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 查看文件对象
     * @return 存储bucket内文件对象信息
     */
    public List<Item> listObjects() {
        Iterable<Result<Item>> results = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(prop.getBucketName()).build());
        List<Item> items = new ArrayList<>();
        try {
            for (Result<Item> result : results) {
                items.add(result.get());
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return items;
    }

    /**
     * 删除
     * @param fileName
     * @return
     * @throws Exception
     */
    public boolean remove(String fileName){
        try {
            minioClient.removeObject( RemoveObjectArgs.builder().bucket(prop.getBucketName()).object(fileName).build());
        }catch (Exception e){
            return false;
        }
        return true;
    }

}

5.文件上传接口



@Api(tags = "文件相关接口")
@Slf4j
@RestController
@RequestMapping(value = "/sys/file/v1/")
public class FileController {


    @Autowired
    private MinioUtil minioUtil;
    @Autowired
    private MinioConfig prop;

    @ApiOperation(value = "查看存储bucket是否存在")
    @GetMapping("/bucketExists")
    public Result bucketExists(String bucketName) {
        return Result.success(minioUtil.bucketExists(bucketName));
    }

    @ApiOperation(value = "创建存储bucket")
    @GetMapping("/makeBucket")
    public Result makeBucket(String bucketName) {
        minioUtil.makeBucket(bucketName);
        return Result.success();
    }

    @ApiOperation(value = "删除存储bucket")
    @GetMapping("/removeBucket")
    public Result removeBucket(String bucketName) {
        minioUtil.removeBucket(bucketName);
        return Result.success();
    }

    @ApiOperation(value = "获取全部bucket")
    @GetMapping("/getAllBuckets")
    public Result<List<Bucket>> getAllBuckets() {
        List<Bucket> allBuckets = minioUtil.getAllBuckets();
        return Result.success(allBuckets);
    }

    @ApiOperation(value = "文件上传返回url")
    @PostMapping("/upload")
    public Result<String> upload(@RequestParam(value = "file") MultipartFile file) {
        String objectName = minioUtil.upload(file);
        if (null != objectName) {
            return Result.success(prop.getEndpoint() + "/" + prop.getBucketName() + "/" + objectName);
        }
        return Result.fail();
    }

    @ApiOperation(value = "图片/视频预览")
    @GetMapping("/preview")
    public Result preview(@RequestParam("fileName") String fileName) {
        return Result.success(minioUtil.preview(fileName));
    }

    @ApiOperation(value = "文件下载")
    @GetMapping("/download")
    public Result download(@RequestParam("fileName") String fileName, HttpServletResponse res) {
        minioUtil.download(fileName,res);
        return Result.success();
    }

    @ApiOperation(value = "删除文件", notes = "根据url地址删除文件")
    @PostMapping("/delete")
    public Result remove(String url) {
        String objName = url.substring(url.lastIndexOf(prop.getBucketName()+"/") + prop.getBucketName().length()+1);
        minioUtil.remove(objName);
        return Result.success();
    }

}

二、根据minio-client依赖实现上传下载

1.引入依赖

<dependency>
     <groupId>com.kotei.framework</groupId>
     <artifactId>minio-client</artifactId>
     <version>0.0.2-SNAPSHOT</version>
</dependency>

2.配置地址

3.MinioUtils

 注意,这里download返回的是一个JSONObject对象,他的data值格式为一个下载链接,所以我们要直接下载链接还要再写 一点,见下面controller层。

@Component
@Slf4j
public class MinIoUtils {

    @Resource
    private MinIoService minIoService;

    @Resource
    private TokenService tokenService;

    public static final String K11 = "k11-";

    /**
     * 上传文件到 minIo
     *
     * @param file   上传的文件
     * @param siteId 站点id
     */
    public String minIoUpload(MultipartFile file, Long siteId) {
        try {
            String extName = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf(".")).toLowerCase();
            String dataFileName = UUID.randomUUID().toString();
            String fileName = dataFileName + extName;
            log.info(">>>>>>>>>>>>>>>>>>> file uploading...");
            JSONObject jsonObject = minIoService.uploadByStream(K11 + siteId, fileName, file);
            if ("200".equalsIgnoreCase(jsonObject.getString("code"))) {
                log.info(">>>>>>>>>>>>>>>>>>> file upload success {}", jsonObject.get("data"));
            }
            return fileName;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(">>>>>>>>>>>>>> file upload failed");
            return null;
        }
    }


    /**
     * 下载
     */
    public JSONObject download(KProjectFileEntity form) {
        JSONObject object = null;
        //文件路径
        String fileUrl = form.getFileUrl();
        try {
            log.error("Excel download: {} file uploading...", form.getFileName());
            object = minIoService.getFileUrl(K11 + tokenService.getSiteId().toString(), fileUrl, 60 * 60);
            log.error("Excel download: {} file upload success", form.getFileName());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("Excel download: {} file upload failed", form.getFileName());
        }

        return object;
    }

}

4.MinioService

@Component
public class MinIoService {

    // 这个是minio服务部署的地址,自己去配置类配置一下。
    @Value("${gossUrl}")
    private String URL;

    private MinIoHttpUtil minIoHttpUtil;

    @PostConstruct
    public void init(){
        minIoHttpUtil=new MinIoHttpUtil();
        minIoHttpUtil.setURL(URL);
    }


    /**
     * 文件上传(返回URL下载地址)
     *
     * @param bucketName 桶名
     * @param fileName   文件名
     * @param file
     * @return: 文件url下载地址
     */
    @SneakyThrows(Exception.class)
    public  JSONObject uploadByStream(String bucketName, String fileName,  MultipartFile file) {
        JSONObject object = minIoHttpUtil.uploadFile("/uploadByStream", bucketName, fileName, file);
        return object;
    }

    

    /**
     *  获取文件下载地址
     *
     * @param bucketName 桶名
     * @param fileName   文件名
     * @param expires Expiry in seconds; defaults to 7 days.
     */
    public  JSONObject getFileUrl(String bucketName, String fileName, Integer expires) {
        String https = minIoHttpUtil.getHttps("/getFileUrl?bucketName=" + bucketName + "&fileName=" + fileName+"&expires=" + expires);
        JSONObject object = JSONObject.parseObject(https);
        return object;

    }

}

5.MinioHttpUtil

public class MinIoHttpUtil {
    private String URL;

    public String getURL() {
        return URL;
    }

    public void setURL(String URL) {
        this.URL = URL;
    }


    public JSONObject uploadFile(String urlStr,String bucketName,String fileName, MultipartFile file) throws IOException {

        RequestConfig defaultRequestConfig = RequestConfig.custom()
                .setSocketTimeout(1000000)
                .setConnectTimeout(1000000)
                .setConnectionRequestTimeout(1000000)
                .setStaleConnectionCheckEnabled(true)
                .build();

        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(defaultRequestConfig)
                .build();
        HttpPost uploadFile = new HttpPost(URL+urlStr);


        DecimalFormat df = new DecimalFormat("#.##");
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        //  HTTP.PLAIN_TEXT_TYPE,HTTP.UTF_8
        builder.addTextBody("bucketName", bucketName, ContentType.TEXT_PLAIN);
        builder.addTextBody("fileName", fileName, ContentType.TEXT_PLAIN);

        // 把文件加到HTTP的post请求中
        // String filepath = "/user/test/123.png"
        // File f = new File(filepath);
        builder.addBinaryBody(
                "file",
                file.getInputStream(),
                // new FileInputStream(f),
                ContentType.APPLICATION_OCTET_STREAM,
                file.getOriginalFilename()
        );

        HttpEntity multipart = builder.build();
        uploadFile.setEntity(multipart);
        CloseableHttpResponse response = httpClient.execute(uploadFile);
        HttpEntity responseEntity = response.getEntity();
        String sResponse= EntityUtils.toString(responseEntity, "UTF-8");
        JSONObject jsonObject = JSONObject.parseObject(sResponse);

        // {"code":1,"data":"7efb19980373dd90f5077576afa7481a","message":""}
        // {"code":401,"httpStatus":null,"data":"373656a2-baff-423a-93fb-704f51003509","message":"error"}

        return jsonObject;

    }



    public String getHttps(String urlParam) {

        HttpURLConnection con = null;

        BufferedReader buffer = null;
        StringBuffer resultBuffer = null;

        try {
            URL url = new URL(URL+urlParam);
            //得到连接对象
            con = (HttpURLConnection) url.openConnection();
            //设置请求类型
            con.setRequestMethod("GET");
            //设置请求需要返回的数据类型和字符集类型
            con.setRequestProperty("Content-Type", "application/json;charset=GBK");
            //允许写出
            con.setDoOutput(true);
            //允许读入
            con.setDoInput(true);
            //不使用缓存
            con.setUseCaches(false);
            //得到响应码
            int responseCode = con.getResponseCode();

            if(responseCode == HttpURLConnection.HTTP_OK){
                //得到响应流
                InputStream inputStream = con.getInputStream();
                //将响应流转换成字符串
                resultBuffer = new StringBuffer();
                String line;
                buffer = new BufferedReader(new InputStreamReader(inputStream, "GBK"));
                while ((line = buffer.readLine()) != null) {
                    resultBuffer.append(line);
                }
                return resultBuffer.toString();
            }

        }catch(Exception e) {
            e.printStackTrace();
        }
        return "";
    }




}

 6.controller层

 这里是取出JSONObject中字符串形式的下载链接,转换为URL,用代码在服务中打开链接或自动下载,再把文件转换为流形式去储存为一个流数组,对应文件名称数组,最后用hutool中的ZipUtil工具实现多个文件压缩返回。

这里有一个问题要注意,就是文件名称最好不要有汉字,会报错!!!应该是编码格式没有设置,我在这里就不演示了,希望能对你有帮助。

@RequestMapping("/download")
    public ResultBody<T> downloadByProjectId(Long projectId, HttpServletResponse response) throws IOException {
        List<KProjectFileEntity> entities = kProjectFileService.downloadFileByProject(projectId);
        if (entities != null && entities.size() > 0) {
            //被压缩文件InputStream
            InputStream[] fileStreams = new InputStream[entities.size()];
            //被压缩文件名称
            String[] fileNames = new String[entities.size()];
            for (int i = 0; i < entities.size(); i++) {
                JSONObject object = minIoUtils.download(entities.get(i));
                if (object != null) {
                    String data = object.getString("data");
                    URL url = new URL(data);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    // 设置超时间为3秒
                    conn.setConnectTimeout(3 * 1000);
                    // 防止屏蔽程序抓取而返回403错误
                    conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
                    // 得到输入流
                    InputStream is = conn.getInputStream();
                    fileStreams[i] = is;
                    fileNames[i] = entities.get(i).getFileUrl();
                }
            }
            //多个文件压缩成压缩包返回
            ZipUtil.zip(response.getOutputStream(), fileNames, fileStreams);
            return ResultBody.success(null, "文件下载成功");
        }
        return ResultBody.failed(200, "没有可下载文件");
    }
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值