mirror of
https://codeup.aliyun.com/64f7d6b8ce01efaafef1e678/coal/coal.git
synced 2026-01-25 07:46:40 +08:00
完善网盘服务
This commit is contained in:
@@ -34,7 +34,6 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
@@ -54,159 +53,165 @@ public class SignFilter extends OncePerRequestFilter {
|
||||
|
||||
@Autowired RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
private static String getFieldFromHeaderOrQs(HttpServletRequest request, String name) {
|
||||
return StringUtils.defaultIfEmpty(request.getHeader(name), request.getParameter(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(
|
||||
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
if (sysConfigService.isEnable(Constants.SYSCONFIG_ENABLE_REQUEST_SIGN)) {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
|
||||
stopWatch.start("基本请求头");
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
// 请求方法
|
||||
|
||||
sb.append(StringUtils.defaultString(request.getMethod().toUpperCase()));
|
||||
sb.append(StringUtils.defaultString("\n"));
|
||||
|
||||
// 请求地址
|
||||
sb.append(
|
||||
StringUtils.defaultString(
|
||||
ObjectUtils.defaultIfNull(
|
||||
request.getHeader(Constants.HTTP_HEADER_CLIENT_URL),
|
||||
request.getRequestURI())));
|
||||
sb.append(StringUtils.defaultString("\n"));
|
||||
|
||||
// 请求参数
|
||||
sb.append(StringUtils.defaultString(request.getQueryString()));
|
||||
sb.append(StringUtils.defaultString("\n"));
|
||||
|
||||
// 请求头
|
||||
|
||||
String token =
|
||||
ObjectUtils.defaultIfNull(
|
||||
request.getHeader(Constants.HTTP_HEADER_TOKEN), "anonymous");
|
||||
String ts = request.getHeader(Constants.HTTP_HEADER_TS);
|
||||
if (StringUtils.isEmpty(ts)) {
|
||||
RequestUtils.writeResponse(
|
||||
new BizException(Constants.HTTP_HEADER_TS + " 请求头缺失"), response);
|
||||
return;
|
||||
}
|
||||
|
||||
String random = request.getHeader(Constants.HTTP_HEADER_CLIENT_RANDOM);
|
||||
if (StringUtils.isEmpty(random)) {
|
||||
RequestUtils.writeResponse(
|
||||
new BizException(Constants.HTTP_HEADER_CLIENT_RANDOM + " 请求头缺失"), response);
|
||||
return;
|
||||
}
|
||||
long tsi = 0;
|
||||
|
||||
try {
|
||||
|
||||
tsi = Long.parseLong(ts);
|
||||
} catch (Exception e) {
|
||||
RequestUtils.writeResponse(
|
||||
new BizException(Constants.HTTP_HEADER_TS + " 请求头格式错误"), response);
|
||||
return;
|
||||
}
|
||||
|
||||
long current = System.currentTimeMillis();
|
||||
|
||||
if (Math.abs(tsi - current) > TIME_DIFF_MS) {
|
||||
RequestUtils.writeResponse(
|
||||
new BizException(
|
||||
Constants.HTTP_HEADER_TS
|
||||
+ " 客户端时间误差过大,请校准时间. 服务器时间为: "
|
||||
+ LocalDateTime.now()),
|
||||
response);
|
||||
return;
|
||||
}
|
||||
|
||||
sb.append(StringUtils.defaultString(token));
|
||||
|
||||
sb.append(StringUtils.defaultString("\n"));
|
||||
|
||||
sb.append(StringUtils.defaultString(ts));
|
||||
|
||||
sb.append(StringUtils.defaultString("\n"));
|
||||
|
||||
sb.append(StringUtils.defaultString(random));
|
||||
|
||||
sb.append(StringUtils.defaultString("\n"));
|
||||
|
||||
stopWatch.stop();
|
||||
|
||||
stopWatch.start("sha256Hex");
|
||||
|
||||
String sha256Hex;
|
||||
MediaType mediaType =
|
||||
MediaType.parseMediaType(
|
||||
ObjectUtils.defaultIfNull(
|
||||
request.getContentType(),
|
||||
MediaType.APPLICATION_OCTET_STREAM_VALUE));
|
||||
// 文件上传不对body进行签名
|
||||
if (mediaType.isCompatibleWith(MediaType.MULTIPART_FORM_DATA)) {
|
||||
|
||||
sha256Hex = DigestUtils.sha256Hex("").toUpperCase();
|
||||
|
||||
} else {
|
||||
sha256Hex = DigestUtils.sha256Hex(request.getInputStream()).toUpperCase();
|
||||
}
|
||||
|
||||
sb.append(StringUtils.defaultString(sha256Hex));
|
||||
sb.append(StringUtils.defaultString("\n"));
|
||||
|
||||
stopWatch.stop();
|
||||
|
||||
stopWatch.start("签名");
|
||||
|
||||
Mac mac =
|
||||
HmacUtils.getInitializedMac(
|
||||
HmacAlgorithms.HMAC_SHA_256, token.getBytes(StandardCharsets.UTF_8));
|
||||
mac.update(sb.toString().getBytes(StandardCharsets.UTF_8));
|
||||
String sign = Hex.encodeHexString(mac.doFinal()).toUpperCase();
|
||||
|
||||
stopWatch.stop();
|
||||
|
||||
String clientSign = request.getHeader(Constants.HTTP_HEADER_CLIENT_SIGN);
|
||||
|
||||
if (!sign.equals(clientSign)) {
|
||||
log.debug("key: {} \ndata:{}", token, sb);
|
||||
log.warn("签名错误: {} {}", clientSign, sign);
|
||||
sysLogService.saveSysLog(request, "签名模块", "签名错误", clientSign + " " + sign);
|
||||
RequestUtils.writeResponse(
|
||||
new BizException(Constants.HTTP_HEADER_CLIENT_SIGN + " 请求头签名错误"), response);
|
||||
return;
|
||||
}
|
||||
|
||||
stopWatch.start("重复请求");
|
||||
String cr =
|
||||
redisTemplate.opsForValue().get(Constants.CACHE_CLIENT_RANDOM_PREFIX + random);
|
||||
|
||||
if (StringUtils.equals(cr, "1")) {
|
||||
sysLogService.saveSysLog(request, "签名模块", "重复请求", "");
|
||||
RequestUtils.writeResponse(new BizException("请求已过期, 请刷新页面重试"), response);
|
||||
return;
|
||||
} else {
|
||||
redisTemplate
|
||||
.opsForValue()
|
||||
.set(
|
||||
Constants.CACHE_CLIENT_RANDOM_PREFIX + random,
|
||||
"1",
|
||||
TIME_DIFF_MS,
|
||||
TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
stopWatch.stop();
|
||||
|
||||
if (request instanceof CacheBodyRequestWrapper cacheBodyRequestWrapper) {
|
||||
cacheBodyRequestWrapper.reset();
|
||||
}
|
||||
|
||||
log.debug("签名验证通过: {}", stopWatch.prettyPrint());
|
||||
if (!sysConfigService.isEnable(Constants.SYSCONFIG_ENABLE_REQUEST_SIGN)) {
|
||||
doFilter(request, response, filterChain);
|
||||
return;
|
||||
}
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
|
||||
stopWatch.start("基本请求头");
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
// 请求方法
|
||||
|
||||
sb.append(StringUtils.defaultString(request.getMethod().toUpperCase()));
|
||||
sb.append(StringUtils.defaultString("\n"));
|
||||
|
||||
// 请求地址
|
||||
sb.append(
|
||||
StringUtils.defaultString(
|
||||
ObjectUtils.defaultIfNull(
|
||||
getFieldFromHeaderOrQs(request, Constants.HTTP_HEADER_CLIENT_URL),
|
||||
request.getRequestURI())));
|
||||
sb.append(StringUtils.defaultString("\n"));
|
||||
|
||||
// 请求参数
|
||||
sb.append(StringUtils.defaultString(request.getQueryString()));
|
||||
sb.append(StringUtils.defaultString("\n"));
|
||||
|
||||
// 请求头
|
||||
|
||||
String token =
|
||||
ObjectUtils.defaultIfNull(
|
||||
getFieldFromHeaderOrQs(request, Constants.HTTP_HEADER_TOKEN), "anonymous");
|
||||
String ts = getFieldFromHeaderOrQs(request, Constants.HTTP_HEADER_TS);
|
||||
if (StringUtils.isEmpty(ts)) {
|
||||
RequestUtils.writeResponse(
|
||||
new BizException(Constants.HTTP_HEADER_TS + " 请求头缺失"), response);
|
||||
return;
|
||||
}
|
||||
|
||||
String random = getFieldFromHeaderOrQs(request, Constants.HTTP_HEADER_CLIENT_RANDOM);
|
||||
if (StringUtils.isEmpty(random)) {
|
||||
RequestUtils.writeResponse(
|
||||
new BizException(Constants.HTTP_HEADER_CLIENT_RANDOM + " 请求头缺失"), response);
|
||||
return;
|
||||
}
|
||||
long tsi = 0;
|
||||
|
||||
try {
|
||||
|
||||
tsi = Long.parseLong(ts);
|
||||
} catch (Exception e) {
|
||||
RequestUtils.writeResponse(
|
||||
new BizException(Constants.HTTP_HEADER_TS + " 请求头格式错误"), response);
|
||||
return;
|
||||
}
|
||||
|
||||
long current = System.currentTimeMillis();
|
||||
|
||||
if (Math.abs(tsi - current) > TIME_DIFF_MS) {
|
||||
RequestUtils.writeResponse(
|
||||
new BizException(
|
||||
Constants.HTTP_HEADER_TS
|
||||
+ " 客户端时间误差过大,请校准时间. 服务器时间为: "
|
||||
+ LocalDateTime.now()),
|
||||
response);
|
||||
return;
|
||||
}
|
||||
|
||||
sb.append(StringUtils.defaultString(token));
|
||||
|
||||
sb.append(StringUtils.defaultString("\n"));
|
||||
|
||||
sb.append(StringUtils.defaultString(ts));
|
||||
|
||||
sb.append(StringUtils.defaultString("\n"));
|
||||
|
||||
sb.append(StringUtils.defaultString(random));
|
||||
|
||||
sb.append(StringUtils.defaultString("\n"));
|
||||
|
||||
stopWatch.stop();
|
||||
|
||||
stopWatch.start("sha256Hex");
|
||||
|
||||
String sha256Hex;
|
||||
MediaType mediaType =
|
||||
MediaType.parseMediaType(
|
||||
ObjectUtils.defaultIfNull(
|
||||
request.getContentType(),
|
||||
MediaType.APPLICATION_OCTET_STREAM_VALUE));
|
||||
// 文件上传不对body进行签名
|
||||
if (mediaType.isCompatibleWith(MediaType.MULTIPART_FORM_DATA)) {
|
||||
|
||||
sha256Hex = DigestUtils.sha256Hex("").toUpperCase();
|
||||
|
||||
} else {
|
||||
sha256Hex = DigestUtils.sha256Hex(request.getInputStream()).toUpperCase();
|
||||
}
|
||||
|
||||
sb.append(StringUtils.defaultString(sha256Hex));
|
||||
sb.append(StringUtils.defaultString("\n"));
|
||||
|
||||
stopWatch.stop();
|
||||
|
||||
stopWatch.start("签名");
|
||||
|
||||
Mac mac =
|
||||
HmacUtils.getInitializedMac(
|
||||
HmacAlgorithms.HMAC_SHA_256, token.getBytes(StandardCharsets.UTF_8));
|
||||
mac.update(sb.toString().getBytes(StandardCharsets.UTF_8));
|
||||
String sign = Hex.encodeHexString(mac.doFinal()).toUpperCase();
|
||||
|
||||
stopWatch.stop();
|
||||
|
||||
String clientSign = getFieldFromHeaderOrQs(request, Constants.HTTP_HEADER_CLIENT_SIGN);
|
||||
|
||||
if (!sign.equals(clientSign)) {
|
||||
log.debug("key: {} \ndata:{}", token, sb);
|
||||
log.warn("签名错误: {} {}", clientSign, sign);
|
||||
sysLogService.saveSysLog(request, "签名模块", "签名错误", clientSign + " " + sign);
|
||||
RequestUtils.writeResponse(
|
||||
new BizException(Constants.HTTP_HEADER_CLIENT_SIGN + " 请求头签名错误"), response);
|
||||
return;
|
||||
}
|
||||
|
||||
stopWatch.start("重复请求");
|
||||
String cr =
|
||||
redisTemplate.opsForValue().get(Constants.CACHE_CLIENT_RANDOM_PREFIX + random);
|
||||
|
||||
if (StringUtils.equals(cr, "1")) {
|
||||
sysLogService.saveSysLog(request, "签名模块", "重复请求", "");
|
||||
RequestUtils.writeResponse(new BizException("请求已过期, 请刷新页面重试"), response);
|
||||
return;
|
||||
} else {
|
||||
redisTemplate
|
||||
.opsForValue()
|
||||
.set(
|
||||
Constants.CACHE_CLIENT_RANDOM_PREFIX + random,
|
||||
"1",
|
||||
TIME_DIFF_MS,
|
||||
TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
stopWatch.stop();
|
||||
|
||||
if (request instanceof CacheBodyRequestWrapper cacheBodyRequestWrapper) {
|
||||
cacheBodyRequestWrapper.reset();
|
||||
}
|
||||
|
||||
log.debug("签名验证通过: {}", stopWatch.prettyPrint());
|
||||
|
||||
doFilter(request, response, filterChain);
|
||||
}
|
||||
|
||||
@@ -26,13 +26,39 @@ import java.util.List;
|
||||
public class NetDiskController {
|
||||
@Autowired private NetDiskService service;
|
||||
|
||||
|
||||
|
||||
@PostMapping("/getById")
|
||||
public NetDiskDto getById(@RequestBody IdRequest request) {
|
||||
return this.service.getById(request.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* id转路径
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/idToPath")
|
||||
public String idToPath(@RequestBody IdRequest request) {
|
||||
return this.service.idToPath(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 路径转id
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/pathToId")
|
||||
public String pathToId(@RequestBody IdRequest request) {
|
||||
return this.service.pathToId(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出下级文件和文件夹
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/ls")
|
||||
@SysLog(action = "ls", message = "id")
|
||||
public List<NetDiskDto> ls(@RequestBody IdRequest request) {
|
||||
@@ -40,29 +66,71 @@ public class NetDiskController {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 列出文件树
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/tree")
|
||||
public NetDiskTreeDto tree(@RequestBody IdRequest request) {
|
||||
return this.service.tree(request);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建文件夹
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/createDir")
|
||||
@SysLog(action = "createDir", message = "name")
|
||||
public NetDiskDto createDir (@RequestBody CreateDirDto request) {
|
||||
public NetDiskDto createDir(@RequestBody CreateDirDto request) {
|
||||
return this.service.createDir(request);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量创建文件夹
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/batchCreateDir")
|
||||
@SysLog(action = "createDir", message = "names.join(',')")
|
||||
public List<NetDiskDto> batchCreateDir (@RequestBody BatchCreateDirDto request) {
|
||||
public List<NetDiskDto> batchCreateDir(@RequestBody BatchCreateDirDto request) {
|
||||
return this.service.batchCreateDir(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 预创建文件, 创建文件之前调用, 用于秒传和文件分片进度
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/preCreateFile")
|
||||
@SysLog(action = "preCreateFile", message = "name")
|
||||
|
||||
public PreCreateFileDto preCreateFile (@RequestBody CreateFileDto request) {
|
||||
public PreCreateFileDto preCreateFile(@RequestBody CreateFileDto request) {
|
||||
return this.service.preCreateFile(request);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建文件分片
|
||||
*
|
||||
* @param parent
|
||||
* @param size
|
||||
* @param sha256
|
||||
* @param mineType
|
||||
* @param multipartFile
|
||||
* @param ossKey
|
||||
* @param name
|
||||
* @param code
|
||||
* @param remarks
|
||||
* @param sortKey
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/createFileSlice")
|
||||
public NetDiskDto createFileSlice (
|
||||
public NetDiskDto createFileSlice(
|
||||
@RequestParam("parent") String parent,
|
||||
@RequestParam("size") Long size,
|
||||
@RequestParam("sha256") String sha256,
|
||||
@@ -72,11 +140,8 @@ public class NetDiskController {
|
||||
@RequestParam("name") String name,
|
||||
@RequestParam("code") String code,
|
||||
@RequestParam("remarks") String remarks,
|
||||
@RequestParam("sortKey") String sortKey
|
||||
@RequestParam("sortKey") String sortKey) {
|
||||
|
||||
|
||||
|
||||
) {
|
||||
CreateFileDto request = new CreateFileDto();
|
||||
request.setParent(parent);
|
||||
request.setSize(size);
|
||||
@@ -87,32 +152,44 @@ public class NetDiskController {
|
||||
request.setName(name);
|
||||
request.setCode(code);
|
||||
request.setRemarks(remarks);
|
||||
try{
|
||||
try {
|
||||
|
||||
request.setSortKey(Integer.valueOf(sortKey));
|
||||
}catch (Exception e){
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
|
||||
return this.service.createFileSlice(request);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建文件
|
||||
*
|
||||
* @param parent
|
||||
* @param size
|
||||
* @param sha256
|
||||
* @param mineType
|
||||
* @param multipartFile
|
||||
* @param ossKey
|
||||
* @param name
|
||||
* @param code
|
||||
* @param remarks
|
||||
* @param sortKey
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/createFile")
|
||||
public NetDiskDto createFile (
|
||||
@RequestParam("parent") String parent,
|
||||
@RequestParam("size") Long size,
|
||||
@RequestParam("sha256") String sha256,
|
||||
@RequestParam("mineType") String mineType,
|
||||
@RequestParam("multipartFile") MultipartFile multipartFile,
|
||||
@RequestParam("ossKey") String ossKey,
|
||||
@RequestParam("name") String name,
|
||||
@RequestParam("code") String code,
|
||||
@RequestParam("remarks") String remarks,
|
||||
@RequestParam("sortKey") String sortKey
|
||||
public NetDiskDto createFile(
|
||||
@RequestParam("parent") String parent,
|
||||
@RequestParam("size") Long size,
|
||||
@RequestParam("sha256") String sha256,
|
||||
@RequestParam("mineType") String mineType,
|
||||
@RequestParam("multipartFile") MultipartFile multipartFile,
|
||||
@RequestParam("ossKey") String ossKey,
|
||||
@RequestParam("name") String name,
|
||||
@RequestParam("code") String code,
|
||||
@RequestParam("remarks") String remarks,
|
||||
@RequestParam("sortKey") String sortKey) {
|
||||
|
||||
|
||||
|
||||
) {
|
||||
CreateFileDto request = new CreateFileDto();
|
||||
request.setParent(parent);
|
||||
request.setSize(size);
|
||||
@@ -123,51 +200,96 @@ public class NetDiskController {
|
||||
request.setName(name);
|
||||
request.setCode(code);
|
||||
request.setRemarks(remarks);
|
||||
try{
|
||||
try {
|
||||
|
||||
request.setSortKey(Integer.valueOf(sortKey));
|
||||
}catch (Exception e){
|
||||
request.setSortKey(Integer.valueOf(sortKey));
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
|
||||
return this.service.createFile(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/move")
|
||||
@SysLog(action = "move", message = "srcId + ' -> ' + targetId")
|
||||
|
||||
public NetDiskDto move(@RequestBody MoveDto request) {
|
||||
return this.service.move(request);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 复制
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/copy")
|
||||
@SysLog(action = "copy", message = "srcId + ' -> ' + targetId")
|
||||
public NetDiskDto copy (@RequestBody CopyDto request) {
|
||||
public NetDiskDto copy(@RequestBody CopyDto request) {
|
||||
return this.service.copy(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/remove")
|
||||
@SysLog(action = "remove", message = "id")
|
||||
public Object remove (@RequestBody IdRequest request) {
|
||||
public Object remove(@RequestBody IdRequest request) {
|
||||
this.service.remove(request);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过阿里云OSS链接下载文件夹
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
*/
|
||||
@PostMapping("/downloadDir")
|
||||
@SysLog(action = "downloadDir", message = "id")
|
||||
public void remove (@RequestBody IdRequest request, HttpServletResponse response) {
|
||||
public void downloadDir(@RequestBody IdRequest request, HttpServletResponse response) {
|
||||
|
||||
this.service.downloadDir(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过阿里云OSS链接下载文件
|
||||
*
|
||||
* @param id
|
||||
* @param attachment
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/downloadFile")
|
||||
public ResponseEntity<Object> downloadFile(
|
||||
@RequestParam("id") String id,
|
||||
@RequestParam(value = "attachment", defaultValue = "false") Boolean attachment) {
|
||||
|
||||
public ResponseEntity<Object> downloadFile(@RequestParam("id") String id, @RequestParam(value = "attachment", defaultValue = "false") Boolean attachment) {
|
||||
|
||||
|
||||
return ResponseEntity.status(HttpStatus.TEMPORARY_REDIRECT).header("Location", this.service.downloadFile(id, attachment)).body(null);
|
||||
return ResponseEntity.status(HttpStatus.TEMPORARY_REDIRECT)
|
||||
.header("Location", this.service.downloadFile(id, attachment))
|
||||
.body(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 本地下载文件
|
||||
*
|
||||
* @param id
|
||||
* @param attachment
|
||||
* @param response
|
||||
*/
|
||||
@GetMapping("/downloadFileLocal")
|
||||
public void downloadFile(
|
||||
@RequestParam("id") String id,
|
||||
@RequestParam(value = "attachment", defaultValue = "false") Boolean attachment,
|
||||
HttpServletResponse response) {
|
||||
|
||||
this.service.downloadFileLocal(id, attachment, response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package cn.lihongjie.coal.netDisk.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Data
|
||||
public class NetDiskTreeDto extends NetDiskDto {
|
||||
|
||||
private List<NetDiskTreeDto> children = new ArrayList<>();
|
||||
|
||||
}
|
||||
@@ -31,4 +31,10 @@ public interface NetDiskMapper
|
||||
NetDiskEntity toEntity(CreateFileDto request);
|
||||
|
||||
List<NetDiskDto> toDto(List<NetDiskEntity> children);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(source = "children", target = "children", ignore = false, qualifiedByName = "copyChildrenTree" )
|
||||
})
|
||||
@Named("copyChildrenTree")
|
||||
NetDiskTreeDto toTreeDto(NetDiskEntity root);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package cn.lihongjie.coal.netDisk.repository;
|
||||
import cn.lihongjie.coal.base.dao.BaseRepository;
|
||||
import cn.lihongjie.coal.netDisk.entity.NetDiskEntity;
|
||||
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
@@ -22,4 +24,47 @@ public interface NetDiskRepository extends BaseRepository<NetDiskEntity> {
|
||||
List<NetDiskEntity> findALlByParentNullAndOrganizationId(String organizationId);
|
||||
|
||||
long countByParentNullAndOrganizationIdAndName(String organizationId, String name);
|
||||
|
||||
@Query(
|
||||
value =
|
||||
"""
|
||||
|
||||
with recursive
|
||||
tmp as (select t.*, 0 as level
|
||||
from t_net_disk t
|
||||
where t.id = :id
|
||||
union all
|
||||
|
||||
select p.*, t.level + 1 as level
|
||||
from t_net_disk p
|
||||
inner join tmp t on p.id = t.parent_id),
|
||||
|
||||
tmp2 as (select * from tmp order by level desc)
|
||||
|
||||
|
||||
select string_agg(name, '/')
|
||||
from tmp2
|
||||
""",
|
||||
nativeQuery = true)
|
||||
String idToPath(@Param("id") String id);
|
||||
|
||||
@Query(
|
||||
value =
|
||||
"""
|
||||
|
||||
with recursive tmp as (select regexp_split_to_array(:path, '/') as arr)
|
||||
, tmp2 as (select tmp.arr, 1 as index, t.id as id, ARRAY_LENGTH(tmp.arr, 1) as len
|
||||
from tmp
|
||||
inner join t_net_disk t on t.parent_id is null and t.organization_id = :organizationId
|
||||
union all
|
||||
|
||||
select tx.arr as arr, tx.index + 1 as index, t.id as id, tx.len
|
||||
from t_net_disk t
|
||||
inner join tmp2 tx on t.parent_id = tx.id and t.name = tx.arr[tx.index + 1])
|
||||
|
||||
select id
|
||||
from tmp2 where index = len
|
||||
""",
|
||||
nativeQuery = true)
|
||||
String pathToId(@Param("path") String path, @Param("organizationId") String organizationId);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -47,10 +48,7 @@ import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@@ -65,6 +63,42 @@ public class NetDiskService extends BaseService<NetDiskEntity, NetDiskRepository
|
||||
@Autowired private NetDiskMapper mapper;
|
||||
@Autowired private ConversionService conversionService;
|
||||
|
||||
public String idToPath(IdRequest request) {
|
||||
|
||||
String id = request.getId();
|
||||
String ans = idToPath(id);
|
||||
return StringUtils.startsWith(ans, "//")? StringUtils.substring(ans, 1): ans;
|
||||
}
|
||||
|
||||
private String idToPath(String id) {
|
||||
|
||||
return this.repository.idToPath(id);
|
||||
}
|
||||
|
||||
public String pathToId(IdRequest request) {
|
||||
|
||||
String id = this.repository.pathToId(request.getId(), Ctx.currentUser().getOrganizationId());
|
||||
|
||||
if (StringUtils.isEmpty(id)) {
|
||||
throw new BizException("路径不存在");
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
private NetDiskEntity findRoot() {
|
||||
|
||||
try {
|
||||
|
||||
return findRootDir().get(0);
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
|
||||
IdRequest request = new IdRequest("/");
|
||||
handlerRootDir(request);
|
||||
return get(request.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkEntry(CreateFileDto request, List<NetDiskEntity> allSlice) {
|
||||
if (allSlice.isEmpty() && request.getSliceIndex() != 0) {
|
||||
throw new BizException("第一个分片的index必须是0");
|
||||
@@ -135,24 +169,7 @@ public class NetDiskService extends BaseService<NetDiskEntity, NetDiskRepository
|
||||
private void handlerRootDir(IdRequest request) {
|
||||
if (StringUtils.equals(request.getId(), "/")) {
|
||||
|
||||
List<NetDiskEntity> rootDir =
|
||||
this.repository.findAll(
|
||||
new Specification<NetDiskEntity>() {
|
||||
@Override
|
||||
public Predicate toPredicate(
|
||||
Root<NetDiskEntity> root,
|
||||
CriteriaQuery<?> query,
|
||||
CriteriaBuilder criteriaBuilder) {
|
||||
|
||||
return criteriaBuilder.and(
|
||||
criteriaBuilder.isNull(root.get("parent")),
|
||||
criteriaBuilder.equal(
|
||||
root.get("organizationId"),
|
||||
Ctx.currentUser().getOrganizationId()),
|
||||
criteriaBuilder.equal(root.get("entryType"), "0"),
|
||||
criteriaBuilder.equal(root.get("name"), "/"));
|
||||
}
|
||||
});
|
||||
List<NetDiskEntity> rootDir = findRootDir();
|
||||
|
||||
if (rootDir.isEmpty()) {
|
||||
NetDiskEntity entity = new NetDiskEntity();
|
||||
@@ -168,6 +185,27 @@ public class NetDiskService extends BaseService<NetDiskEntity, NetDiskRepository
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<NetDiskEntity> findRootDir() {
|
||||
return this.repository.findAll(
|
||||
new Specification<NetDiskEntity>() {
|
||||
@Override
|
||||
public Predicate toPredicate(
|
||||
Root<NetDiskEntity> root,
|
||||
CriteriaQuery<?> query,
|
||||
CriteriaBuilder criteriaBuilder) {
|
||||
|
||||
return criteriaBuilder.and(
|
||||
criteriaBuilder.isNull(root.get("parent")),
|
||||
criteriaBuilder.equal(
|
||||
root.get("organizationId"),
|
||||
Ctx.currentUser().getOrganizationId()),
|
||||
criteriaBuilder.equal(root.get("entryType"), "0"),
|
||||
criteriaBuilder.equal(root.get("name"), "/"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public NetDiskDto createDir(CreateDirDto request) {
|
||||
|
||||
validateDirName(request.getName());
|
||||
@@ -741,4 +779,50 @@ public class NetDiskService extends BaseService<NetDiskEntity, NetDiskRepository
|
||||
save(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public void downloadFileLocal(String id, Boolean attachment, HttpServletResponse response) {
|
||||
|
||||
NetDiskEntity disk = get(id);
|
||||
|
||||
if (!disk.getEntryType().equals("1")) {
|
||||
throw new BizException("只能下载文件");
|
||||
}
|
||||
|
||||
String ossKey = disk.getOssKey();
|
||||
|
||||
OSSObject ossObject = ossClient.getObject(aliyunProperty.getOSS().getBucketName(), ossKey);
|
||||
|
||||
response.setContentType(disk.getMineType());
|
||||
|
||||
if (attachment) {
|
||||
response.setHeader(
|
||||
"Content-Disposition",
|
||||
"attachment;filename="
|
||||
+ URLEncoder.encode(disk.getName(), StandardCharsets.UTF_8));
|
||||
|
||||
} else {
|
||||
|
||||
response.setHeader(
|
||||
"Content-Disposition",
|
||||
"inline;filename=" + URLEncoder.encode(disk.getName(), StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
ossObject.getObjectContent().transferTo(response.getOutputStream());
|
||||
}
|
||||
|
||||
public NetDiskTreeDto tree(IdRequest request) {
|
||||
|
||||
handlerRootDir(request);
|
||||
|
||||
if (StringUtils.isEmpty(request.getId())) {
|
||||
return this.mapper.toTreeDto(findRoot());
|
||||
}
|
||||
|
||||
NetDiskEntity entity = get(request.getId());
|
||||
|
||||
return this.mapper.toTreeDto(entity);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user