oss桶权限为私密时,列表查看时桶为私密的文件获取临时url(优化列表查看功能,添加下载功能)

This commit is contained in:
chenchen 2022-10-17 17:54:29 +08:00
parent 8665bffcff
commit a79fda4d05
8 changed files with 133 additions and 49 deletions

View File

@ -15,6 +15,8 @@ import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.ServiceException;
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.bo.SysOssBo;
import com.ruoyi.system.domain.vo.SysOssVo;
@ -96,23 +98,7 @@ public class SysOssController extends BaseController {
@SaCheckPermission("system:oss:download")
@GetMapping("/download/{ossId}")
public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException {
SysOssVo sysOss = iSysOssService.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));
iSysOssService.download(ossId,response);
}
/**

View File

@ -10,11 +10,6 @@ import java.util.List;
*/
public interface OssConstant {
/**
* OSS模块KEY
*/
String SYS_OSS_KEY = "sys_oss:";
/**
* 默认配置KEY
*/

View File

@ -172,11 +172,10 @@ public class OssClient {
}
public String getPrivateUrl(String objectKey, Integer second) {
// objectKey = "file/2022/10/13/81eef51cb0734dedbfa616493a021fe4.jpg";
GeneratePresignedUrlRequest generatePresignedUrlRequest =
new GeneratePresignedUrlRequest(properties.getBucketName(), objectKey)
.withMethod(HttpMethod.GET)
.withExpiration(new Date(Instant.now().toEpochMilli() + 1000 * second));
.withExpiration(new Date(System.currentTimeMillis() + 1000 * second));
URL url = client.generatePresignedUrl(generatePresignedUrlRequest);
return url.toString();
}

View File

@ -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;
}

View File

@ -7,6 +7,8 @@ import com.ruoyi.system.domain.bo.SysOssBo;
import com.ruoyi.system.domain.vo.SysOssVo;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
@ -25,6 +27,8 @@ public interface ISysOssService {
SysOss upload(MultipartFile file);
void download(Long ossId, HttpServletResponse response) throws IOException;
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@ -1,6 +1,9 @@
package com.ruoyi.system.service.impl;
import cn.hutool.core.convert.Convert;
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.toolkit.Wrappers;
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.utils.JsonUtils;
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.oss.constant.OssConstant;
import com.ruoyi.oss.core.OssClient;
import com.ruoyi.oss.entity.UploadResult;
import com.ruoyi.oss.enumd.AccessPolicyType;
import com.ruoyi.oss.exception.OssException;
import com.ruoyi.oss.factory.OssFactory;
import com.ruoyi.oss.properties.OssProperties;
@ -24,9 +30,11 @@ import com.ruoyi.system.mapper.SysOssMapper;
import com.ruoyi.system.service.ISysOssService;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
@ -49,19 +57,7 @@ public class SysOssServiceImpl implements ISysOssService {
public TableDataInfo<SysOssVo> queryPageList(SysOssBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<SysOss> lqw = buildQueryWrapper(bo);
Page<SysOssVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
List<SysOssVo> filterResult = result.getRecords().stream().map(o -> {
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());
List<SysOssVo> filterResult = result.getRecords().stream().map(this::matchingUrl).collect(Collectors.toList());
result.setRecords(filterResult);
return TableDataInfo.build(result);
}
@ -98,6 +94,27 @@ public class SysOssServiceImpl implements ISysOssService {
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
public SysOss upload(MultipartFile file) {
String originalfileName = file.getOriginalFilename();
@ -133,4 +150,24 @@ public class SysOssServiceImpl implements ISysOssService {
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;
}
}

View File

@ -80,6 +80,7 @@
<el-table-column label="桶名称" align="center" prop="bucketName" />
<el-table-column label="前缀" align="center" prop="prefix" />
<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">
<template slot-scope="scope">
<el-switch
@ -151,14 +152,11 @@
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="AccessPolicy">
<el-form-item label="桶权限类型">
<el-radio-group v-model="form.accessPolicy">
<el-radio
v-for="dict in dict.type.access_policy"
:key="dict.value"
:label="dict.value"
>{{dict.label}}</el-radio>
<el-radio label="0">private</el-radio>
<el-radio label="1">public</el-radio>
<el-radio label="2">custom</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="域" prop="region">
@ -189,7 +187,7 @@ import {
export default {
name: "OssConfig",
dicts: ['sys_yes_no', 'sys_normal_disable','access_policy'],
dicts: ['sys_yes_no', 'sys_normal_disable'],
data() {
return {
// loading
@ -218,6 +216,21 @@ export default {
isHttpsOptions: [],
// (0 1)
statusOptions: [],
//
accessPolicyOptions: [
{
label: 'private',
value: 0
},
{
label: 'public',
value: 1
},
{
label: 'custom',
value: 2
}
],
//
queryParams: {
pageNum: 1,
@ -392,7 +405,17 @@ export default {
}).catch(() => {
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>
}
}
}
};
</script>

View File

@ -31,9 +31,14 @@
<el-table-column label="邮箱" prop="email" :show-overflow-tooltip="true" />
<el-table-column label="手机" prop="phonenumber" :show-overflow-tooltip="true" />
<el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
</template>
<!-- <template slot-scope="scope"> -->
<div slot="status" slot-scope="text, record">
<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 label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">