当前位置:网站首页>文件 - 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;
}
边栏推荐
猜你喜欢
随机推荐
TypeScript编译(tsconfig.json)
cp 的用法
【Star项目】小帽飞机大战(七)
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
tidyverse笔记——管道函数
js原型详解
How to use repeating-linear-gradient
英语翻译软件-批量自动免费翻译软件支持三方接口翻译
编辑时过滤当前节点及根据限制的层数过滤数据
深度解析 z-index
SQLite数据库连接字符串
ls的用法
【云原生】-Docker安装部署分布式数据库 OceanBase
关于求反三角函数的三角函数值
TCP/IP协议和互联网协议群
【云原生】3.3 Kubernetes 中间件部署实战
DirectExchange switch simple introduction demo
In-depth analysis of z-index
Explain the example + detail the difference between @Resource and @Autowired annotations (the most complete in the entire network)
浅析瀑布流布局原理及实现方式








