likes
comments
collection
share

我是怎么做到开源系统中的文件上传等功能的?

作者站长头像
站长
· 阅读数 14

写在前面:

最近有一个想法,做一个程序员师徒系统。因为在大学期间的我在学习java的时候非常地迷茫,找不到自己的方向,也没有一个社会上有经验的前辈去指导,所以走了很多的弯路。后来工作了,想把自己的避坑经验分享给别人,但是发现身边都是有经验的开发者,也没有机会去分享自己的想法,所以富贵同学就想做一个程序员专属的师徒系统,秉承着徒弟能够有人指教少走弯路,师傅能桃李满天下的目的,所以开始做这个师徒系统,也会同步更新该系统所用到的技术,并且作为教程分享给大家,希望大家能够关注一波。

我是怎么做到开源系统中的文件上传等功能的?

minio在该项目中实现的核心文件为:MinioConfig,MinioUtil,FileController 做这个的目的想的是聊天的过程中肯定会有文件的发送,所以我选择了minio去集成,用springboot集成minio首先介绍一下什么是minio: minio是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。 然后再感谢spring-minio提供的思路,该教程作为他的升级版补充了一些sdk的api。 如果没有安装minio请参照: blog.csdn.net/csdnerM/art…

第一步,我们导入minio的jar包

 		 <!--minio-->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.2.0</version>
        </dependency>
        <!--minio-->

第二步,编写配置类

package com.wangfugui.apprentice.config;

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

@Configuration
public class MinioConfig {
	
	@Value("${minio.url}")
    private String url;
    @Value("${minio.accessKey}")
    private String accessKey;
    @Value("${minio.secretKey}")
    private String secretKey;
    
    @Bean
    public MinioClient getMinioClient() {
        return MinioClient.builder().endpoint(url)
				.credentials(accessKey, secretKey).build();
    }
    
}

这一步的目的是将MinioClient 给注入到spring的容器中以供我们使用

第三步,编写util类

package com.wangfugui.apprentice.common.util;

import com.wangfugui.apprentice.dao.dto.Fileinfo;
import io.minio.BucketExistsArgs;
import io.minio.CopyObjectArgs;
import io.minio.CopySource;
import io.minio.GetObjectArgs;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.ListObjectsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveBucketArgs;
import io.minio.RemoveObjectArgs;
import io.minio.Result;
import io.minio.StatObjectArgs;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

@Component
public class MinioUtil {
	@Autowired
    private MinioClient minioClient;
	
	/**
	 * 创建一个桶
	 */
	public void createBucket(String bucket) throws Exception {
		boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
		if (!found) {
			minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
		}
	}
	
	/**
	 * 上传一个文件
	 */
	public void uploadFile(InputStream stream, String bucket, String objectName) throws Exception {
		minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName)
				.stream(stream, -1, 10485760).build());
	}
	
	/**
	 * 列出所有的桶
	 */
	public List<String> listBuckets() throws Exception {
		List<Bucket> list = minioClient.listBuckets();
		List<String> names = new ArrayList<>();
		list.forEach(b -> {
			names.add(b.name());
		});
		return names;
	}
	
	/**
	 * 列出一个桶中的所有文件和目录
	 */
	public List<Fileinfo> listFiles(String bucket) throws Exception {
		Iterable<Result<Item>> results = minioClient.listObjects(
			    ListObjectsArgs.builder().bucket(bucket).recursive(true).build());
			
			List<Fileinfo> infos = new ArrayList<>();
				results.forEach(r->{
					Fileinfo info = new Fileinfo();
					try {
						Item item = r.get();
						info.setFilename(item.objectName());
						info.setDirectory(item.isDir());
						infos.add(info);
					} catch (Exception e) {
						e.printStackTrace();
					}
				});
		return infos;
	}
	
	/**
	 * 下载一个文件
	 */
	public InputStream download(String bucket, String objectName) throws Exception {
		InputStream stream = minioClient.getObject(
		              GetObjectArgs.builder().bucket(bucket).object(objectName).build());
		return stream;
	}
	
	/**
	 * 删除一个桶
	 */
	public void deleteBucket(String bucket) throws Exception {
		minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());
	}
	
	/**
	 * 删除一个对象
	 */
	public void deleteObject(String bucket, String objectName) throws Exception {
		minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectName).build());
	}


	/**
	 * 复制文件
	 *
	 * @Param: [sourceBucket, sourceObject, targetBucket, targetObject]
	 * @return: void
	 * @Author: MrFugui
	 * @Date: 2021/11/15
	 */
	public void copyObject(String sourceBucket, String sourceObject, String targetBucket, String targetObject) throws Exception {
		this.createBucket(targetBucket);
		minioClient.copyObject(CopyObjectArgs.builder().bucket(targetBucket).object(targetObject)
				.source(CopySource.builder().bucket(sourceBucket).object(sourceObject).build()).build());
	}

	/**
	 * 获取文件信息
	 *
	 * @Param: [bucket, objectName]
	 * @return: java.lang.String
	 * @Author: MrFugui
	 * @Date: 2021/11/15
	 */
	public String getObjectInfo(String bucket, String objectName) throws Exception {

		return minioClient.statObject(StatObjectArgs.builder().bucket(bucket).object(objectName).build()).toString();

	}

	/**
	 * 生成一个给HTTP GET请求用的presigned URL。浏览器/移动端的客户端可以用这个URL进行下载,即使其所在的存储桶是私有的。
	 *
	 * @Param: [bucketName, objectName, expires]
	 * @return: java.lang.String
	 * @Author: MrFugui
	 * @Date: 2021/11/15
	 */
	public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) throws Exception {
		GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs
				.builder().bucket(bucketName).object(objectName).expiry(expires).method(Method.GET).build();
		return minioClient.getPresignedObjectUrl(build);
	}

	/**
	 * 获取minio中所有的文件
	 *
	 * @Param: []
	 * @return: java.util.List<boot.spring.domain.Fileinfo>
	 * @Author: MrFugui
	 * @Date: 2021/11/15
	 */
	public List<Fileinfo> listAllFile() throws Exception {
		List<String> list = this.listBuckets();
		List<Fileinfo> fileinfos = new ArrayList<>();
		for (String bucketName : list) {
			fileinfos.addAll(this.listFiles(bucketName));
		}


		return fileinfos;
	}

}

这里集成了minio sdk中的api 这是minio的api文档

第四步,编写controller类

package com.wangfugui.apprentice.controller;

import com.wangfugui.apprentice.common.util.MinioUtil;
import com.wangfugui.apprentice.common.util.ResponseUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;

@Api(tags = "文件操作接口")
@RestController
@RequestMapping(value = "/file")
public class FileController {

    @Autowired
    MinioUtil minioUtil;

    @ApiOperation("上传一个文件")
    @RequestMapping(value = "/uploadfile", method = RequestMethod.POST)
    public ResponseUtils fileupload(@RequestParam MultipartFile uploadfile, @RequestParam String bucket,
                                    @RequestParam(required = false) String objectName) throws Exception {
        minioUtil.createBucket(bucket);
        if (objectName != null) {
            minioUtil.uploadFile(uploadfile.getInputStream(), bucket, objectName + "/" + uploadfile.getOriginalFilename());
        } else {
            minioUtil.uploadFile(uploadfile.getInputStream(), bucket, uploadfile.getOriginalFilename());
        }
        return ResponseUtils.success();
    }

    @ApiOperation("列出所有的桶")
    @RequestMapping(value = "/listBuckets", method = RequestMethod.GET)
    public ResponseUtils listBuckets() throws Exception {
        return ResponseUtils.success(minioUtil.listBuckets());
    }

    @ApiOperation("递归列出一个桶中的所有文件和目录")
    @RequestMapping(value = "/listFiles", method = RequestMethod.GET)
    public ResponseUtils listFiles(@RequestParam String bucket) throws Exception {
        return ResponseUtils.success(minioUtil.listFiles(bucket));
    }

    @ApiOperation("下载一个文件")
    @RequestMapping(value = "/downloadFile", method = RequestMethod.GET)
    public void downloadFile(@RequestParam String bucket, @RequestParam String objectName,
                             HttpServletResponse response) throws Exception {
        InputStream stream = minioUtil.download(bucket, objectName);
        ServletOutputStream output = response.getOutputStream();
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(objectName.substring(objectName.lastIndexOf("/") + 1), "UTF-8"));
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("UTF-8");
        IOUtils.copy(stream, output);
    }


    @ApiOperation("删除一个文件")
    @RequestMapping(value = "/deleteFile", method = RequestMethod.GET)
    public ResponseUtils deleteFile(@RequestParam String bucket, @RequestParam String objectName) throws Exception {
        minioUtil.deleteObject(bucket, objectName);
        return ResponseUtils.success();
    }

    @ApiOperation("删除一个桶")
    @RequestMapping(value = "/deleteBucket", method = RequestMethod.GET)
    public ResponseUtils deleteBucket(@RequestParam String bucket) throws Exception {
        minioUtil.deleteBucket(bucket);
        return ResponseUtils.success();
    }


    @ApiOperation("复制一个文件")
    @GetMapping("/copyObject")
    public ResponseUtils copyObject(@RequestParam String sourceBucket, @RequestParam String sourceObject, @RequestParam String targetBucket, @RequestParam String targetObject) throws Exception {
        minioUtil.copyObject(sourceBucket, sourceObject, targetBucket, targetObject);
        return ResponseUtils.success();
    }

    @GetMapping("/getObjectInfo")
    @ApiOperation("获取文件信息")
    public ResponseUtils getObjectInfo(@RequestParam String bucket, @RequestParam String objectName) throws Exception {

        return ResponseUtils.success(minioUtil.getObjectInfo(bucket, objectName));
    }

    @GetMapping("/getPresignedObjectUrl")
    @ApiOperation("获取一个连接以供下载")
    public ResponseUtils getPresignedObjectUrl(@RequestParam String bucket, @RequestParam String objectName, @RequestParam Integer expires) throws Exception {

        return ResponseUtils.success(minioUtil.getPresignedObjectUrl(bucket, objectName, expires));
    }

    @GetMapping("/listAllFile")
    @ApiOperation("获取minio中所有的文件")
    public ResponseUtils listAllFile() throws Exception {

        return ResponseUtils.success(minioUtil.listAllFile());
    }


}

注意这里的ResponseUtils请去往仓库中领取,仓库地址: SpringBoot+MinIO

妈耶,完了在yml中配置minio的地址,你没发现吧,叫你上课不认真听 我是怎么做到开源系统中的文件上传等功能的?

第五步,配置yml文件

minio:
  url: http://1localhost:9000  #对象存储服务的URL
  accessKey: root #账户
  secretKey: 123456 #密码

这步咋来的?请看我的Linux安装MinIO

第六步,启动项目,访问api

我是怎么做到开源系统中的文件上传等功能的? 就ok啦!! 到这里就完成了springboot集成minio实现文件的上传等功能

拓展: 通过链接访问文件

我是怎么做到开源系统中的文件上传等功能的? 下载minio client

wget https://dl.min.io/client/mc/release/linux-amd64/mc

我是怎么做到开源系统中的文件上传等功能的? 赋予权限

chmod a+x mc

我是怎么做到开源系统中的文件上传等功能的?

添加minio server

./mc config host add minio http://ip:port admin passwd

设置需要开放下载的bucket, 注意需要带minio

./mc  policy  set  download  minio/yourbucket

浏览器访问

http://ip:9000/apprentice/xxxx.png

说在之后

师徒系统我会一直更新,因为是开源的项目,所以我也希望又更多的小伙伴加入进来!! 这是程序员师徒管理系统的地址: 程序员师徒管理系统 我是怎么做到开源系统中的文件上传等功能的?