最近需要使用Minio替代原来的SFTP服务器,在此记录相关操作

一、目的

对于整个系统需要一个高可用且能进行复杂权限校验文件管理功能,故此需要一个统一管理文件文件管理服务可以设置相关文件上传格式大小权限等。

Minio作为一个非常成熟的分布式存储框架,拥有丰富的SDK支持,所以使用Minio主要实现方案

二、Minio安装

我这次安装主要参考网上博文教程

Minio:分布式数据存储搭建 – 知乎

三、Minio相关配置

            <dependency>
                &lt;groupId&gt;io.minio</groupId&gt;
                <artifactId&gt;minio</artifactId&gt;
                <version>8.4.1</version>
            </dependency>
# Minio配置
minio:
  url: http://127.0.0.1:19000
  # 账号
  accessKey: xxxxx
  # 密码
  secretKey: xxxxx
  # MinIO桶名字
  bucketName: xxxxx


/**
 * Minio 配置信息
 */
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {
    /**
     * 服务地址
     */
    private String url;

    /**
     * 用户名
     */
    private String accessKey;

    /**
     * 密码
     */
    private String secretKey;

    /**
     * 存储名称
     */
    private String bucketName;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getAccessKey() {
        return accessKey;
    }

    public void setAccessKey(String accessKey) {
        this.accessKey = accessKey;
    }

    public String getSecretKey() {
        return secretKey;
    }

    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }

    public String getBucketName() {
        return bucketName;
    }

    public void setBucketName(String bucketName) {
        this.bucketName = bucketName;
    }

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

minio工具


@Slf4j
@Component
@RefreshScope
public class MinioUtil {
    @Autowired
    private MinioClient minioClient;

    @Value("${file.url.auth.origin:}")
    private String originAuthUrl;

    @Value("${file.url.auth.replace:}")
    private String replaceAuthUrl;

    @Value("${file.url.notauth.origin:}")
    private String originNotAuthUrl;

    @Value("${file.url.notauth.replace:}")
    private String replaceNotAuthUrl;

    /**
     * 上传文件流
     *
     * @param objectPath  文件路径+文件名
     * @param inputStream 文件流
     * @param bucket      桶名称
     */
    public void upload(String objectPath, InputStream inputStream, String bucket) {
        log.info("上传文件 objectPath = {}", objectPath);
        try {
            minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectPath).stream(inputStream, inputStream.available(), -1).build());
        } catch (Exception e) {
            log.error("上传文件出错 objectPath = {}", objectPath, e);
            throw new FilestoreException(FileResultEnum.FILE_UPLOAD_FAIL);
        }
    }

    /**
     * 上传文件字节数组
     *
     * @param objectPath 文件路径+文件名
     * @param byteArr    文件字节数组
     * @param bucket     桶名称
     * @return
     */
    public void upload(String objectPath, byte[] byteArr, String bucket) {
        upload(objectPath, new ByteArrayInputStream(byteArr), bucket);
    }

    /**
     * 判断文件是否存在
     *
     * @param objectPath 文件路径+文件名
     * @param bucket     桶名称
     * @return
     */
    public boolean isExists(String objectPath, String bucket) {
        boolean exist = true;
        try {
            minioClient.statObject(StatObjectArgs.builder().bucket(bucket).object(objectPath).build());
        } catch (Exception e) {
            log.info("文件{}不存在", objectPath);
            exist = false;
        }
        return exist;
    }

    /**
     * 下载文件字节数组
     *
     * @param objectPath 文件路径+文件名
     * @param bucket     桶名称
     * @return
     */
    public byte[] download(String objectPath, String bucket) {
        log.info("下载文件字节数组 filename = {}", objectPath);
        try (InputStream stream = minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(bucket)
                        .object(objectPath)
                        .build())) {
            return IOUtils.toByteArray(stream);
        } catch (Exception e) {
            log.error("下载文件出错 objectPath = {}", objectPath, e);
            throw new FilestoreException(FileResultEnum.DOWNLOAD_FILE_FAIL);
        }
    }

    /**
     * 下载文件到本地
     *
     * @param objectPath 文件路径+文件名
     * @param savePath   存储目录
     * @param fileName   文件名
     * @param bucket     桶名称
     */
    public void download(String objectPath, String savePath, String fileName, String bucket) {
        log.info("下载文件到本地 name = {}, savePath = {}", objectPath, savePath);
        try {
            // 路径遍历漏洞
            savePath = XssCleanRuleUtils.xssCleanFile(savePath);
            File file = FileUtils.getFile(savePath);
            if (!file.exists()) {
                if (file.mkdirs()) {
                    log.info("文件创建成功");
                } else {
                    log.info("文件创建失败");
                }
            }
            minioClient.downloadObject(DownloadObjectArgs.builder()
                    .bucket(bucket)
                    .object(objectPath)
                    .filename(savePath + File.separator + fileName)
                    .build());
        } catch (Exception e) {
            log.error("下载文件到本地出错 objectPath = {}, savePath = {}", objectPath, savePath, e);
            throw new FilestoreException(FileResultEnum.DOWNLOAD_FILE_FAIL);
        }
    }

    public String getUrl(String objectPath, String bucket) {
        log.info("获取文件下载地址 name = {}", objectPath);
        try {
            String url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(Method.GET)
                    .bucket(bucket)
                    .object(objectPath)
                    .build());
            if (FilePathConstant.AUTH_BUCKET.equals(bucket)) {
                return url.replace(originAuthUrl, replaceAuthUrl);
            } else {
                return url.replace(originNotAuthUrl, replaceNotAuthUrl);
            }
        } catch (Exception e) {
            log.error("获取文件地址出错 objectPath = {}", objectPath, e);
            throw new FilestoreException(FileResultEnum.DOWNLOAD_FILE_FAIL);
        }
    }

    public void delete(String objectPath, String bucket) {
        log.info("删除文件 name = {}", objectPath);
        try {
            minioClient.removeObject(RemoveObjectArgs.builder()
                    .bucket(bucket)
                    .object(objectPath)
                    .build());
        } catch (Exception e) {
            log.error("删除文件出错 objectPath = {}", objectPath, e);
            throw new FilestoreException(FileResultEnum.DELETE_FILE_FAIL);
        }
    }

三、nginx配置

为了避免大文件在各个服务之间的传输从而导致带宽占用,所以使用nginx内部重定向(X-Accel-Redirect)来获取文件。

文件类型主要分为两大类:

一、不需要鉴权的文件

任何人不需要任何校验,则可以通过链接直接下载访问相关的文件。

location ^~  /static {
           alias   /sftp/sftpuser/files/not/;
           try_files $uri $uri/ /index.html;
        }

二、需要鉴权的文件

用户先要经过后台相关校验才能下载访问相关的文件。

nginx需要在 location加入internal“, 声明仅限内部调用

location /auth {
                internal;
                alias /sftp/sftpuser;
        }

java代码也需要在返回response里面加上X-Accel-Redirect重定向

public BaseResult<DownloadResponse> downloadWeb(String number, String operationType, String password, HttpServletResponse response) throws IOException {
        // 下载-返回给前台文件流
        DownloadResponse downloadResponse = fileInfoService.downloadFile(number, operationType, password);
        log.info("下载返回参数 downloadResponse={}", downloadResponse);
        response = FileDownloadUtils.setResponseByDownload(response, downloadResponse.getFileName());
        response.setHeader("Content-Type", "application/octet-stream");
        //HTTP响应截断漏洞
        response.setHeader("X-Accel-Redirect", URLEncoder.encode(XssCleanRuleUtils.xssClean(downloadResponse.getFilePath().replace(baseUrl, "")),
                "UTF-8"));
        response.setHeader("X-Accel-Buffering", "yes");//是否使用Nginx缓存默认yes
        return BaseResult.success(downloadResponse);
    }

原文地址:https://blog.csdn.net/qq_847601290/article/details/127366099

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_27478.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注