当前位置:网站首页>文件 - 03 下载文件:根据文件id获取下载链接
文件 - 03 下载文件:根据文件id获取下载链接
2022-07-31 05:48:00 【追风筝~】
系列文章:
整体思路:
1. 根据文件id获取下载链接
@RestController
@ResponseBody
@ResponseResult
@Slf4j
@RequestMapping("/ngsoc/PORTAL/api/v1")
@Api(tags = "File")
public class FileController {
@ApiOperation(value = "根据文件id获取下载链接", httpMethod = "GET")
@RequestMapping(value = "/files/downloadLink/{fileId}", method = RequestMethod.GET)
public DownloadLinkResponse getDownloadLink(
@ApiParam(value = "文件id", required = true) @PathVariable("fileId") String fileId
) throws UploadDownloadFileException {
FileInfo fileInfo = fileDao.existFileId(fileId);
fileIdAuthorityServiceImpl.assertThisUserHaveAuthority(fileInfo);
if (ObjectUtils.isEmpty(fileInfo)) {
throw new UploadDownloadFileException(I18nUtils.i18n("exception.file.input.id"));
}
String downloadLink = fileService.getDownloadLink(fileId);
DownloadLinkResponse downloadLinkResponse = new DownloadLinkResponse();
downloadLinkResponse.setDownloadLink(downloadLink);
return downloadLinkResponse;
}
}
@Data
public class DownloadLinkResponse {
private String downloadLink;
}
2. 判断文件id是否存在
FileInfo fileInfo = fileDao.existFileId(fileId);
@Mapper
@Repository
public interface IFileMapper {
/** * 判断文件id是否存在 * * @param fileId * @return */
FileInfo existFileId(@Param("fileId") String fileId);
}
<select id="existFileId" parameterType="String" resultType="portal.model.entity.FileInfo">
SELECT fileId FROM t_upload_file
where fileId = #{fileId} and <include refid="unexpiredFilter"/>
</select>
<!-- 大于号 >-->
<!-- 永不过期 neverExpire = 1,或者未过期的,即过期时间 >= 当前时间 -->
<sql id="unexpiredFilter">
(neverExpire = 1 or expireTime >= current_timestamp())
</sql>
3. 确定用户拥有操作这个fileId的权限
fileIdAuthorityServiceImpl.assertThisUserHaveAuthority(fileInfo);
public interface FileIdAuthorityService {
/** * 确定用户拥有操作这个fileId的权限 * <p> * 否则报错 * * @param fileInfo fileInfo * @return FileInfo * @throws FileIdAuthorityException 当用户无权限操作该文件时 */
@Nullable
FileInfo assertThisUserHaveAuthority(@Nullable FileInfo fileInfo);
}
@Slf4j
@Service
public class FileIdAuthorityServiceImpl implements FileIdAuthorityService {
@Nullable
@Override
public FileInfo assertThisUserHaveAuthority(@Nullable FileInfo fileInfo) {
if (fileInfo == null) {
return null;
}
String userName = SpringSecurityUtil.getCurrentUserNameFromSpringSecurity();
return this.assertThisUserHaveAuthority(fileInfo, userName);
}
@Nullable
@Override
public FileInfo assertThisUserHaveAuthority(@Nullable FileInfo fileInfo, @Nullable String userName) {
log.debug("assertThisUserHaveAuthority : fileInfo : {} , userName : {}", fileInfo, userName);
if (fileInfo == null) {
return null;
}
if (fileInfo.getShare() == null || fileInfo.getShare() == FileInfoShareEnum.SHARE_TO_ALL.getValue()) {
return fileInfo;
}
if (StringUtils.equalsAny(
userName,
"transfer",
fileInfo.getFileUploader()
)) {
// 按照当前云soc权限设计,凡是API调用都是transfer账户
return fileInfo;
}
throw new FileIdAuthorityException(
fileInfo.getFileId(),
userName
);
}
}
4. 根据文件Id获取含token 的文件下载连接
public interface IFileService {
/** * 根据文件Id获取含token 的文件下载连接 * * @param fileId 文件Id * @return */
String getDownloadLink(String fileId);
/** * redis保存文件token、id的键值对 * * @param token * @param id * @throws DataAccessException */
void saveDownloadLinkTokenId(String token, String id) throws DataAccessException;
}
@Controller
@Slf4j
public class FileServiceImpl implements IFileService {
@Autowired
private FileConfig fileConfig;
@Autowired
private RedisTemplate<String, String> stringRedisTemplate;
@Override
public String getDownloadLink(String fileId) throws DataAccessException {
// 生成token
String downloadLinkToken = UuidUtils.uuidWithoutMinus();
// 文件的下载链接:/ngsoc/PORTAL/api/v1/files/fetch/downloadLinkToken
String downloadLink = fileConfig.getDownloadLinkBase().concat(downloadLinkToken);
// 将token 和 fileId进行绑定并设置过期时间
saveDownloadLinkTokenId(downloadLinkToken, fileId);
return downloadLink;
}
// 将token和fileId绑定并设置过期时间
@Override
public void saveDownloadLinkTokenId(String token, String id) throws DataAccessException {
Boolean flag = stringRedisTemplate.opsForValue()
.setIfAbsent(token, id, fileConfig.getTokenExpireTime(), TimeUnit.MINUTES);
if (BooleanUtils.isNotTrue(flag)) {
log.error("save downloadLinkToken-fileId failed.");
throw new RedisDataAccessException("exception.file.redis.save");
}
}
}
5. 读取配置文件信息
ngsoc:
file:
savePath: /opt/ngsoc/data/local/upload/
tokenExpireTime: 10
downloadLinkBase: /ngsoc/PORTAL/api/v1/files/fetch/
content-type:
- image
white-suffix: [ pdf, doc, xml, html, doc, docx, txt, wps, xls, xlsx, png, jpg, jpeg, gif, rtf, bmp, icon, mpg, zip, rar, 7z, ppt, pptx ]
white-urls:
- /api/v1/files/fetch/*
folderSize: 8
folderSizeUnit: G
# 临时文件的过期时间,默认半天 12h
expireTimeForTempFile: 12h
# 清理过期文件任务的冷静期,暂定为 30min
calmingPeriodOfClearTask: 30min
@Data
@Configuration
@ConfigurationProperties(prefix = "ngsoc.file")
public class FileConfig {
/** * 临时文件的默认过期时间 */
public static final String DEFAULT_EXPIRE_TIME_FOR_TEMP_FILE = "12h";
/** * 冷静期的默认时间 */
public static final String DEFAULT_CALMING_PERIOD_OF_CLEAR_TASK = "30min";
/** * 附件的保存路径 * */
private String savePath;
/** * token的失效时间 * */
private Integer tokenExpireTime;
/** * 附件下载的路径 * */
private String downloadLinkBase;
/** * 文件类型 * */
private List<String> contentType;
/** * 附件白名单后缀 * */
private List<String> whiteSuffix;
/** * 白名单 */
private List<String> whiteUrls;
/** * 文件最小尺寸 * */
private Integer minFileSize;
/** * 文件大小 * */
private Integer folderSize;
/** * 文件大小的单位 * */
private String folderSizeUnit;
/** * 临时文件的失效时间 * */
private String expireTimeForTempFile;
/** * 任务清理的周期 * */
private String calmingPeriodOfClearTask;
}
边栏推荐
- Run the NPM will pop up to ask "how are you going to open this file?"
- 文本三剑客之e`grep,seq文本编辑工具
- Automatic translation software - batch batch automatic translation software recommendation
- R——避免使用 col=0
- tidyverse笔记——tidyr包
- codec2 BlockPool:不可读库
- nohup principle
- Log4net 思维导图
- DDL+DML+DQL
- Install the gstreamer development dependency library to the project sysroot directory
猜你喜欢
《白帽子说Web安全》思维导图
服务器和客户端信息的获取
搭建zabbix监控及邮件报警(超详细教学)
Zotero | Zotero translator plugin update | Solve the problem that Baidu academic literature cannot be obtained
LeetCode刷题——摆动序列#376#Medium
Automatic translation software - batch batch automatic translation software recommendation
深度解析 z-index
银河麒麟高级服务器v10 sp1 手动加载Raid卡驱动
Zotero | Zotero translator插件更新 | 解决百度学术文献无法获取问题
熟悉而陌生的新朋友——IAsyncDisposable
随机推荐
shell的脚本的基本用法
(border-box) The difference between box model w3c and IE
Install the gstreamer development dependency library to the project sysroot directory
一文读懂 MongoDB 和 MySQL 的差异
gstreamer的caps event和new_segment event
进程和计划任务管理
shell之条件语句(test、if、case)
LeetCode brush # 376 # Medium - swing sequence
How to choose a suitable UI component library in uni-app
新瓶陈酒 --- 矩阵快速幂
防抖和节流
线程中断方法
Database Principles Homework 2 — JMU
How to use repeating-linear-gradient
单点登录 思维导图
接口报错no message avaliable
What is float?What is document flow?Several ways and principles of clearing floats?What is BFC, how to trigger BFC, the role of BFC
【 TA - frost Wolf _may - "one hundred plan" 】 art 2.3 hard surface
数据库原理作业2 — JMU
Postgresql source code learning (34) - transaction log ⑩ - full page write mechanism