bug修复

This commit is contained in:
liang.chao 2025-10-23 19:17:56 +08:00
parent 4a48b4ee1c
commit b1e6eabc26
10 changed files with 343 additions and 6 deletions

View File

@ -149,7 +149,7 @@ public class ArchiveController extends BaseController {
// 如果子集有数据 无法修改
Integer child = archiveMapper.getchild(dto);
if (child > 0){
return R.fail("该节点下有子集,无法修改");
return R.fail("该节点下存在子节点或该节点下存在档案文件,无法修改");
}
Integer num = service.geMaxSort(vo.getParentId().toString());
if (num == null) {
@ -176,7 +176,7 @@ public class ArchiveController extends BaseController {
if (i > 0) {
return R.ok();
} else {
return R.fail("该节点下有子集,无法删除");
return R.fail("该节点下存在子节点或该节点下存在档案文件,无法删除");
}
} catch (Exception e) {
log.error(e.toString(), e);

View File

@ -289,7 +289,7 @@ public class FileManagementController extends BaseController {
try {
Integer child = fileManageMapper.getchild(dto);
if (child > 0){
return R.fail("该节点下有子集,无法修改");
return R.fail("该节点下存在子节点或该节点下存在档案文件,无法修改");
}
Integer num = fileManageService.getMaxSort(dto);
if (num == null) {
@ -314,7 +314,7 @@ public class FileManagementController extends BaseController {
try {
Integer child = fileManageMapper.getchild(dto);
if (child > 0){
return R.fail("该节点下有子集,无法删除");
return R.fail("该节点下存在子节点或该节点下存在档案文件,无法删除");
}
Integer i = fileManageService.delFileManage(dto);
if (i > 0) {

View File

@ -0,0 +1,68 @@
package com.bonus.web.controller.tool;
import com.bonus.common.annotation.RequiresPermissions;
import com.bonus.common.annotation.SysLog;
import com.bonus.common.core.controller.BaseController;
import com.bonus.common.core.domain.AjaxResult;
import com.bonus.common.core.domain.R;
import com.bonus.common.core.page.TableDataInfo;
import com.bonus.common.enums.OperaType;
import com.bonus.system.domain.KyDataClassify;
import com.bonus.system.domain.KyDataCollectData;
import com.bonus.system.domain.vo.KyDataClassifyVo;
import com.bonus.web.service.FileShareService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
/**
* @Authorliang.chao
* @Date2025/10/23 - 14:07
*/
@RestController
@RequestMapping("/file/share")
@Slf4j
public class FileShareController extends BaseController {
@Resource
private FileShareService fileShareService;
/**
* 获取数据分类管理下拉框
* @param kyDataClassify
* @return
*/
@RequiresPermissions("file:share:listAll")
@GetMapping("/listAll")
public TableDataInfo listAll(KyDataClassify kyDataClassify)
{
List<KyDataClassifyVo> list = fileShareService.listAll(kyDataClassify);
return getDataTable(list);
}
/**
* 根据数据类型数据汇集管理列表
*
* @param kyDataCollectData
* @return
*/
@SysLog(title = "档案分享管理", businessType = OperaType.QUERY, module = "档案分享管理->档案分享管理", details = "根据档案文件数据汇集管理列表")
@RequiresPermissions("file:share:list")
@GetMapping("/list")
public TableDataInfo list(KyDataCollectData kyDataCollectData) {
List<KyDataCollectData> list = fileShareService.selectKyDataCollectDataList(kyDataCollectData);
return getDataTable(list);
}
@SysLog(title = "档案分享文件详情", businessType = OperaType.QUERY, module = "档案分享管理->档案分享管理", details = "档案分享文件详情")
@GetMapping("/queryById")
public void queryById(KyDataCollectData kyDataCollectData, HttpServletResponse response) {
fileShareService.queryDetailById(kyDataCollectData,response);
}
}

View File

@ -0,0 +1,24 @@
package com.bonus.web.mapper;
import com.bonus.system.domain.KyDataClassify;
import com.bonus.system.domain.KyDataCollectData;
import com.bonus.system.domain.vo.KyDataClassifyVo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @Authorliang.chao
* @Date2025/10/23 - 14:45
*/
@Mapper
public interface FileShareMapper {
List<KyDataClassifyVo> getParenList();
List<KyDataClassify> listAll(KyDataClassify kyDataClassify);
List<KyDataCollectData> selectKyDataCollectDataList(KyDataCollectData kyDataCollectData);
String queryDetailById(KyDataCollectData kyDataCollectData);
}

View File

@ -0,0 +1,23 @@
package com.bonus.web.service;
import com.bonus.common.core.domain.R;
import com.bonus.system.domain.KyDataClassify;
import com.bonus.system.domain.KyDataCollectData;
import com.bonus.system.domain.vo.KyDataClassifyVo;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
/**
* @Authorliang.chao
* @Date2025/10/23 - 14:43
*/
public interface FileShareService {
List<KyDataClassifyVo> listAll(KyDataClassify kyDataClassify);
List<KyDataCollectData> selectKyDataCollectDataList(KyDataCollectData kyDataCollectData);
void queryDetailById(KyDataCollectData kyDataCollectData, HttpServletResponse response);
}

View File

@ -0,0 +1,190 @@
package com.bonus.web.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.bonus.common.core.domain.R;
import com.bonus.system.domain.KyDataClassify;
import com.bonus.system.domain.KyDataCollectData;
import com.bonus.system.domain.vo.KyDataClassifyVo;
import com.bonus.web.domain.vo.DaKyProFilesContentsVo;
import com.bonus.web.mapper.FileShareMapper;
import com.bonus.web.service.FileManageService;
import com.bonus.web.service.FileShareService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Authorliang.chao
* @Date2025/10/23 - 14:43
*/
@Service
public class FileShareServiceImpl implements FileShareService {
@Resource
private FileShareMapper fileShareMapper;
@Resource
private FileManageService fileManageService;
@Value("${bonus.profile}")
private String uploadDir;
@Override
public List<KyDataClassifyVo> listAll(KyDataClassify kyDataClassify) {
//获取父级
List<KyDataClassifyVo> KyDataClassifyVoList = fileShareMapper.getParenList();
if (KyDataClassifyVoList.size() > 0) {
//获取子级
for (KyDataClassifyVo kyDataClassifyVo : KyDataClassifyVoList) {
kyDataClassify.setPid(kyDataClassifyVo.getCode());
List<KyDataClassify> kyDataClassifyList = fileShareMapper.listAll(kyDataClassify);
kyDataClassifyVo.setKyDataClassifyList(kyDataClassifyList);
}
}
return KyDataClassifyVoList;
}
@Override
public List<KyDataCollectData> selectKyDataCollectDataList(KyDataCollectData kyDataCollectData) {
return fileShareMapper.selectKyDataCollectDataList(kyDataCollectData);
}
@Override
public void queryDetailById(KyDataCollectData kyDataCollectData, HttpServletResponse response) {
try {
String jsonData = fileShareMapper.queryDetailById(kyDataCollectData);
if (jsonData != null) {
JSONArray objects = JSON.parseArray(jsonData);
for (Object obj : objects) {
JSONObject object = (JSONObject) obj;
if (object != null) {
String id = object.getString("id");
if (id.equals(kyDataCollectData.getJsonId().toString())) {
DaKyProFilesContentsVo record = fileManageService.getFileById(Long.parseLong(id));
if (record == null || StringUtils.isBlank(record.getFilePath())) {
response.setStatus(HttpStatus.NOT_FOUND.value());
return;
}
String safeFullPath = buildSecureFullPath(uploadDir, record.getFilePath());
if (safeFullPath == null) {
response.setStatus(HttpStatus.BAD_REQUEST.value());
return;
}
File file = new File(safeFullPath);
if (!file.exists() || !file.isFile()) {
response.setStatus(HttpStatus.NOT_FOUND.value());
return;
}
// 设置响应头
String contentType = getContentType(record.getSuffixName());
response.setContentType(contentType);
String encodedFileName = URLEncoder.encode(record.getFileName(), String.valueOf(StandardCharsets.UTF_8))
.replaceAll("\\+", "%20");
response.setHeader("Content-Disposition", "inline; filename*=UTF-8''" + encodedFileName);
// 写入文件流到响应
Files.copy(file.toPath(), response.getOutputStream());
response.flushBuffer();
return;
}
}
}
}
response.setStatus(HttpStatus.NOT_FOUND.value());
} catch (Exception e) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
}
}
private String getContentType(String suffix) {
if (StringUtils.isBlank(suffix)) {
return "application/octet-stream";
}
switch (suffix.toLowerCase()) {
case "jpg":
case "jpeg":
return "image/jpeg";
case "png":
return "image/png";
case "gif":
return "image/gif";
case "bmp":
return "image/bmp";
case "webp":
return "image/webp";
case "svg":
return "image/svg+xml";
default:
return "application/octet-stream";
}
}
private String buildSecureFullPath(String baseDir, String filePath) {
if (StringUtils.isBlank(filePath)) {
return null;
}
// 统一路径分隔符
String unifiedPath = filePath.replace('\\', '/');
// 移除开头的斜杠
unifiedPath = unifiedPath.replaceAll("^/+", "");
// 检查路径遍历
if (unifiedPath.contains("../") || unifiedPath.contains("..\\")) {
return null;
}
// 检查绝对路径
if (unifiedPath.matches("^[a-zA-Z]:/.*") || unifiedPath.startsWith("/")) {
return null;
}
// 构建完整路径
String fullPath;
if (baseDir.endsWith(File.separator)) {
fullPath = baseDir + unifiedPath;
} else {
fullPath = baseDir + File.separator + unifiedPath;
}
// 使用File的getCanonicalPath进行最终验证
try {
File canonicalFile = new File(fullPath);
String canonicalPath = canonicalFile.getCanonicalPath();
// 验证是否仍在基础目录内
String canonicalBaseDir = new File(baseDir).getCanonicalPath();
if (!canonicalPath.startsWith(canonicalBaseDir)) {
return null;
}
return canonicalPath;
} catch (IOException e) {
return null;
}
}
}

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bonus.web.mapper.FileShareMapper">
<select id="getParenList" resultType="com.bonus.system.domain.vo.KyDataClassifyVo">
select dict_value as code,dict_label as name
from da_ky_sys_dict_data where dict_type = 'file_share_collect' and status='0'
</select>
<select id="listAll" resultType="com.bonus.system.domain.KyDataClassify">
select id,data_type_name
from da_ky_file_share where del_flag='1' and pid =#{pid}
<if test="dataTypeName!=null">
AND INSTR(data_type_name, #{dataTypeName}) > 0
</if>
</select>
<select id="selectKyDataCollectDataList" resultType="com.bonus.system.domain.KyDataCollectData">
select id,data_classify_id,data_json
from da_ky_file_share_data
where del_flag = '1'
<if test="dataClassifyId!=null">
AND data_classify_id = #{dataClassifyId}
</if>
</select>
<select id="queryDetailById" resultType="java.lang.String">
select data_json
from da_ky_file_share_data
where id = #{id}
</select>
</mapper>

View File

@ -74,6 +74,7 @@ public class ResourcesConfig implements WebMvcConfigurer
.excludePathPatterns("/smartArchives/session/check")
.excludePathPatterns("/smartArchives/sys/config/getConfig")
.excludePathPatterns("/smartArchives/data/Collect/queryById")
.excludePathPatterns("/smartArchives/file/share/queryById")
.excludePathPatterns(EXCLUDEURLS)
.order(-15);
}

View File

@ -112,7 +112,7 @@ public class SecurityConfig
.authorizeHttpRequests((requests) -> {
permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll());
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
requests.antMatchers("/login", "/register", "/captchaImage","/sys/config/getConfig","/session/check","/data/Collect/queryById").permitAll()
requests.antMatchers("/login", "/register", "/captchaImage","/sys/config/getConfig","/session/check","/data/Collect/queryById","/file/share/queryById").permitAll()
// 静态资源可匿名访问
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()

View File

@ -48,7 +48,7 @@ public class ReplayAttackInterceptor implements HandlerInterceptor {
ignoreUrlPatterns.add("/smartArchives/getRouters");
ignoreUrlPatterns.add("/smartArchives/session/check");
ignoreUrlPatterns.add("/smartArchives/sys/config/getConfig");
ignoreUrlPatterns.add("/smartArchives/data/Collect/queryById");
ignoreUrlPatterns.add("/smartArchives/file/share/queryById");
}
private final RedisCache redisUtil;