最近需要使用Minio替代原来的SFTP服务器,在此记录下相关操作。
一、目的
对于整个系统需要有一个高可用且能进行复杂权限校验的文件管理功能,故此需要一个统一管理文件的文件管理服务,可以设置相关联文件上传格式、大小、权限等。
Minio作为一个非常成熟的分布式存储框架,拥有丰富的SDK支持,所以使用Minio主要实现方案。
二、Minio安装
三、Minio相关配置
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<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();
}
}
@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进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。