mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-09-21 02:25:56 +08:00
oss桶权限为私密时,列表查看时桶为私密的文件获取临时url(优化列表查看功能,添加下载功能)
This commit is contained in:
parent
8665bffcff
commit
a79fda4d05
@ -15,6 +15,8 @@ import com.ruoyi.common.core.validate.QueryGroup;
|
|||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
import com.ruoyi.common.utils.file.FileUtils;
|
import com.ruoyi.common.utils.file.FileUtils;
|
||||||
|
import com.ruoyi.oss.core.OssClient;
|
||||||
|
import com.ruoyi.oss.factory.OssFactory;
|
||||||
import com.ruoyi.system.domain.SysOss;
|
import com.ruoyi.system.domain.SysOss;
|
||||||
import com.ruoyi.system.domain.bo.SysOssBo;
|
import com.ruoyi.system.domain.bo.SysOssBo;
|
||||||
import com.ruoyi.system.domain.vo.SysOssVo;
|
import com.ruoyi.system.domain.vo.SysOssVo;
|
||||||
@ -96,23 +98,7 @@ public class SysOssController extends BaseController {
|
|||||||
@SaCheckPermission("system:oss:download")
|
@SaCheckPermission("system:oss:download")
|
||||||
@GetMapping("/download/{ossId}")
|
@GetMapping("/download/{ossId}")
|
||||||
public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
|
public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
|
||||||
SysOssVo sysOss = iSysOssService.getById(ossId);
|
iSysOssService.download(ossId,response);
|
||||||
if (ObjectUtil.isNull(sysOss)) {
|
|
||||||
throw new ServiceException("文件数据不存在!");
|
|
||||||
}
|
|
||||||
FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
|
|
||||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
|
|
||||||
long data;
|
|
||||||
try {
|
|
||||||
data = HttpUtil.download(sysOss.getUrl(), response.getOutputStream(), false);
|
|
||||||
} catch (HttpException e) {
|
|
||||||
if (e.getMessage().contains("403")) {
|
|
||||||
throw new ServiceException("无读取权限, 请在对应的OSS开启'公有读'权限!");
|
|
||||||
} else {
|
|
||||||
throw new ServiceException(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response.setContentLength(Convert.toInt(data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -10,11 +10,6 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public interface OssConstant {
|
public interface OssConstant {
|
||||||
|
|
||||||
/**
|
|
||||||
* OSS模块KEY
|
|
||||||
*/
|
|
||||||
String SYS_OSS_KEY = "sys_oss:";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认配置KEY
|
* 默认配置KEY
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -172,11 +172,10 @@ public class OssClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getPrivateUrl(String objectKey, Integer second) {
|
public String getPrivateUrl(String objectKey, Integer second) {
|
||||||
// objectKey = "file/2022/10/13/81eef51cb0734dedbfa616493a021fe4.jpg";
|
|
||||||
GeneratePresignedUrlRequest generatePresignedUrlRequest =
|
GeneratePresignedUrlRequest generatePresignedUrlRequest =
|
||||||
new GeneratePresignedUrlRequest(properties.getBucketName(), objectKey)
|
new GeneratePresignedUrlRequest(properties.getBucketName(), objectKey)
|
||||||
.withMethod(HttpMethod.GET)
|
.withMethod(HttpMethod.GET)
|
||||||
.withExpiration(new Date(Instant.now().toEpochMilli() + 1000 * second));
|
.withExpiration(new Date(System.currentTimeMillis() + 1000 * second));
|
||||||
URL url = client.generatePresignedUrl(generatePresignedUrlRequest);
|
URL url = client.generatePresignedUrl(generatePresignedUrlRequest);
|
||||||
return url.toString();
|
return url.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
package com.ruoyi.oss.enumd;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 桶访问策略配置
|
||||||
|
*
|
||||||
|
* @author 陈賝
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum AccessPolicyType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* private
|
||||||
|
*/
|
||||||
|
PRIVATE("0"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* public
|
||||||
|
*/
|
||||||
|
PUBLIC("1"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constum
|
||||||
|
*/
|
||||||
|
CONSTUM("2");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private final String type;
|
||||||
|
|
||||||
|
}
|
||||||
@ -7,6 +7,8 @@ import com.ruoyi.system.domain.bo.SysOssBo;
|
|||||||
import com.ruoyi.system.domain.vo.SysOssVo;
|
import com.ruoyi.system.domain.vo.SysOssVo;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -25,6 +27,8 @@ public interface ISysOssService {
|
|||||||
|
|
||||||
SysOss upload(MultipartFile file);
|
SysOss upload(MultipartFile file);
|
||||||
|
|
||||||
|
void download(Long ossId, HttpServletResponse response) throws IOException;
|
||||||
|
|
||||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
package com.ruoyi.system.service.impl;
|
package com.ruoyi.system.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.http.HttpException;
|
||||||
|
import cn.hutool.http.HttpUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
@ -10,10 +13,13 @@ import com.ruoyi.common.core.page.TableDataInfo;
|
|||||||
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
import com.ruoyi.common.utils.JsonUtils;
|
import com.ruoyi.common.utils.JsonUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.file.FileUtils;
|
||||||
|
import com.ruoyi.common.utils.redis.CacheUtils;
|
||||||
import com.ruoyi.common.utils.redis.RedisUtils;
|
import com.ruoyi.common.utils.redis.RedisUtils;
|
||||||
import com.ruoyi.oss.constant.OssConstant;
|
import com.ruoyi.oss.constant.OssConstant;
|
||||||
import com.ruoyi.oss.core.OssClient;
|
import com.ruoyi.oss.core.OssClient;
|
||||||
import com.ruoyi.oss.entity.UploadResult;
|
import com.ruoyi.oss.entity.UploadResult;
|
||||||
|
import com.ruoyi.oss.enumd.AccessPolicyType;
|
||||||
import com.ruoyi.oss.exception.OssException;
|
import com.ruoyi.oss.exception.OssException;
|
||||||
import com.ruoyi.oss.factory.OssFactory;
|
import com.ruoyi.oss.factory.OssFactory;
|
||||||
import com.ruoyi.oss.properties.OssProperties;
|
import com.ruoyi.oss.properties.OssProperties;
|
||||||
@ -24,9 +30,11 @@ import com.ruoyi.system.mapper.SysOssMapper;
|
|||||||
import com.ruoyi.system.service.ISysOssService;
|
import com.ruoyi.system.service.ISysOssService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -49,19 +57,7 @@ public class SysOssServiceImpl implements ISysOssService {
|
|||||||
public TableDataInfo<SysOssVo> queryPageList(SysOssBo bo, PageQuery pageQuery) {
|
public TableDataInfo<SysOssVo> queryPageList(SysOssBo bo, PageQuery pageQuery) {
|
||||||
LambdaQueryWrapper<SysOss> lqw = buildQueryWrapper(bo);
|
LambdaQueryWrapper<SysOss> lqw = buildQueryWrapper(bo);
|
||||||
Page<SysOssVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
Page<SysOssVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||||
List<SysOssVo> filterResult = result.getRecords().stream().map(o -> {
|
List<SysOssVo> filterResult = result.getRecords().stream().map(this::matchingUrl).collect(Collectors.toList());
|
||||||
Object json = RedisUtils.getCacheObject(OssConstant.SYS_OSS_KEY + o.getService());
|
|
||||||
OssProperties properties = JsonUtils.parseObject(json.toString(), OssProperties.class);
|
|
||||||
if (properties == null) {
|
|
||||||
throw new OssException("系统异常, '" + o.getService() + "'配置信息不存在!");
|
|
||||||
}
|
|
||||||
String privateFlag = "0";
|
|
||||||
if (properties.getAccessPolicy().equals(privateFlag)) {
|
|
||||||
OssClient storage = OssFactory.instance(o.getService());
|
|
||||||
o.setUrl(storage.getPrivateUrl(o.getFileName(), 100));
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
result.setRecords(filterResult);
|
result.setRecords(filterResult);
|
||||||
return TableDataInfo.build(result);
|
return TableDataInfo.build(result);
|
||||||
}
|
}
|
||||||
@ -98,6 +94,27 @@ public class SysOssServiceImpl implements ISysOssService {
|
|||||||
return baseMapper.selectVoById(ossId);
|
return baseMapper.selectVoById(ossId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void download(Long ossId, HttpServletResponse response) throws IOException {
|
||||||
|
SysOssVo sysOss = this.matchingUrl(this.getById(ossId));
|
||||||
|
if (ObjectUtil.isNull(sysOss)) {
|
||||||
|
throw new ServiceException("文件数据不存在!");
|
||||||
|
}
|
||||||
|
FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
|
||||||
|
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
|
||||||
|
long data;
|
||||||
|
try {
|
||||||
|
data = HttpUtil.download(sysOss.getUrl(), response.getOutputStream(), false);
|
||||||
|
} catch (HttpException e) {
|
||||||
|
if (e.getMessage().contains("403")) {
|
||||||
|
throw new ServiceException("无读取权限, 请在对应的OSS开启'公有读'权限!");
|
||||||
|
} else {
|
||||||
|
throw new ServiceException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response.setContentLength(Convert.toInt(data));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SysOss upload(MultipartFile file) {
|
public SysOss upload(MultipartFile file) {
|
||||||
String originalfileName = file.getOriginalFilename();
|
String originalfileName = file.getOriginalFilename();
|
||||||
@ -133,4 +150,24 @@ public class SysOssServiceImpl implements ISysOssService {
|
|||||||
return baseMapper.deleteBatchIds(ids) > 0;
|
return baseMapper.deleteBatchIds(ids) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 匹配Url
|
||||||
|
*
|
||||||
|
* @param oss OSS对象
|
||||||
|
* @return oss 匹配Url的OSS对象
|
||||||
|
*/
|
||||||
|
private SysOssVo matchingUrl(SysOssVo oss) {
|
||||||
|
OssProperties properties = JsonUtils.parseObject(
|
||||||
|
CacheUtils.get(CacheNames.SYS_OSS_CONFIG, oss.getService()).toString(),
|
||||||
|
OssProperties.class
|
||||||
|
);
|
||||||
|
if (properties == null) {
|
||||||
|
throw new OssException("系统异常, '" + oss.getService() + "'配置信息不存在!");
|
||||||
|
}
|
||||||
|
if (StringUtils.equals(AccessPolicyType.PRIVATE.getType(), properties.getAccessPolicy())) {
|
||||||
|
OssClient storage = OssFactory.instance(oss.getService());
|
||||||
|
oss.setUrl(storage.getPrivateUrl(oss.getFileName(), 100));
|
||||||
|
}
|
||||||
|
return oss;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,6 +80,7 @@
|
|||||||
<el-table-column label="桶名称" align="center" prop="bucketName" />
|
<el-table-column label="桶名称" align="center" prop="bucketName" />
|
||||||
<el-table-column label="前缀" align="center" prop="prefix" />
|
<el-table-column label="前缀" align="center" prop="prefix" />
|
||||||
<el-table-column label="域" align="center" prop="region" />
|
<el-table-column label="域" align="center" prop="region" />
|
||||||
|
<el-table-column label="桶权限类型" align="center" prop="accessPolicy" :formatter = "accessPolicyStateFormat" />
|
||||||
<el-table-column label="状态" align="center" prop="status">
|
<el-table-column label="状态" align="center" prop="status">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-switch
|
<el-switch
|
||||||
@ -151,14 +152,11 @@
|
|||||||
>{{dict.label}}</el-radio>
|
>{{dict.label}}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="桶权限类型">
|
||||||
<el-form-item label="AccessPolicy">
|
|
||||||
<el-radio-group v-model="form.accessPolicy">
|
<el-radio-group v-model="form.accessPolicy">
|
||||||
<el-radio
|
<el-radio label="0">private</el-radio>
|
||||||
v-for="dict in dict.type.access_policy"
|
<el-radio label="1">public</el-radio>
|
||||||
:key="dict.value"
|
<el-radio label="2">custom</el-radio>
|
||||||
:label="dict.value"
|
|
||||||
>{{dict.label}}</el-radio>
|
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="域" prop="region">
|
<el-form-item label="域" prop="region">
|
||||||
@ -189,7 +187,7 @@ import {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "OssConfig",
|
name: "OssConfig",
|
||||||
dicts: ['sys_yes_no', 'sys_normal_disable','access_policy'],
|
dicts: ['sys_yes_no', 'sys_normal_disable'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// 按钮loading
|
// 按钮loading
|
||||||
@ -218,6 +216,21 @@ export default {
|
|||||||
isHttpsOptions: [],
|
isHttpsOptions: [],
|
||||||
// 状态(0正常 1停用)字典
|
// 状态(0正常 1停用)字典
|
||||||
statusOptions: [],
|
statusOptions: [],
|
||||||
|
// 桶权限类型
|
||||||
|
accessPolicyOptions: [
|
||||||
|
{
|
||||||
|
label: 'private',
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'public',
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'custom',
|
||||||
|
value: 2
|
||||||
|
}
|
||||||
|
],
|
||||||
// 查询参数
|
// 查询参数
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
@ -392,6 +405,16 @@ export default {
|
|||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
row.status = row.status === "0" ? "1" : "0";
|
row.status = row.status === "0" ? "1" : "0";
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
accessPolicyStateFormat(row) {
|
||||||
|
if (row.accessPolicy === "0") {
|
||||||
|
return <span class="el-tag el-tag--warning el-tag--medium el-tag--light" > private </span>
|
||||||
|
} else if (row.accessPolicy === "1") {
|
||||||
|
return <span class="el-tag el-tag--success el-tag--medium el-tag--light" > public </span>
|
||||||
|
} else if (row.accessPolicy === "2") {
|
||||||
|
return <span class="el-tag el-tag--medium el-tag--light" > constum </span>
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -31,9 +31,14 @@
|
|||||||
<el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
|
<el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
|
||||||
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
|
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
|
||||||
<el-table-column label="状态" align="center" prop="status">
|
<el-table-column label="状态" align="center" prop="status">
|
||||||
<template slot-scope="scope">
|
<!-- <template slot-scope="scope"> -->
|
||||||
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
|
<div slot="status" slot-scope="text, record">
|
||||||
</template>
|
<a v-if="record.status == 1" style="color: #000000d9">待审核</a>
|
||||||
|
<a v-if="record.status == 2" style="color: #000000d9">正常</a>
|
||||||
|
<a v-if="record.status == 3" style="color: #f36e48">已驳回</a>
|
||||||
|
<a v-if="record.status == 4" style="color: #000000d9">已禁用</a>
|
||||||
|
</div>
|
||||||
|
<!-- </template> -->
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user