提交代码0326
This commit is contained in:
parent
64a3231f01
commit
fc32e0fecd
@ -98,6 +98,12 @@
|
||||
<artifactId>spring-boot-starter-quartz</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.opencsv</groupId>
|
||||
<artifactId>opencsv</artifactId>
|
||||
<version>5.7.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- spring-elasticsearch搜素-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||
|
@ -426,12 +426,12 @@ public class TsFilesController {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询文件内容接口
|
||||
*
|
||||
* @param id 文件的id
|
||||
* @return 文件内容的纯文本(UTF-8 编码)
|
||||
*/
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 查询文件内容接口
|
||||
* 参数说明 id 文件的ID
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult文件内容的纯文本(UTF-8 编码)
|
||||
***********************************/
|
||||
@Log(module = "实验数据管理", value = "查询文件内容!")
|
||||
@GetMapping("/api/files/content")
|
||||
@ApiOperation("查询文件内容")
|
||||
@ -447,13 +447,12 @@ public class TsFilesController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文件内容接口
|
||||
*
|
||||
* @param id 文件的id
|
||||
* @param content 新的文件内容(HTML/文本)
|
||||
* @return 操作结果
|
||||
*/
|
||||
/**********************************
|
||||
* 用途说明: 保存文件内容接口
|
||||
* 参数说明 id 文件的ID
|
||||
* 参数说明 content 新的文件内容(HTML/文本)
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult操作结果
|
||||
***********************************/
|
||||
@Log(module = "实验数据管理", value = "保存文件内容!")
|
||||
@PostMapping("/save/files/content")
|
||||
@ApiOperation("保存文件内容")
|
||||
@ -470,5 +469,19 @@ public class TsFilesController {
|
||||
}
|
||||
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 批量修改文件中多行多列的内容
|
||||
* 参数说明 request 要修改的文件信息
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult操作结果
|
||||
***********************************/
|
||||
@Log(module = "实验数据管理", value = "批量修改文件中多行多列的内容!")
|
||||
@PostMapping("/batchModify")
|
||||
@ApiOperation("批量修改文件中多行多列的内容")
|
||||
public ResponseResult batchModifyFile(@RequestBody BatchModifyRequest request) throws IOException {
|
||||
tsFilesService.batchUpdateFile(request.getId(), request.getModifications());
|
||||
return ResponseResult.success("文件保存成功");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
package com.yfd.platform.modules.experimentalData.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
// 批量修改请求对象
|
||||
@Data
|
||||
public class BatchModifyRequest {
|
||||
|
||||
@NotBlank
|
||||
private String id; // 文件ID
|
||||
|
||||
@NotEmpty
|
||||
private List<ModifyCommand> modifications;
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package com.yfd.platform.modules.experimentalData.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
// 单条修改指令
|
||||
@Data
|
||||
public class ModifyCommand {
|
||||
|
||||
@Min(1)
|
||||
private int lineNum; // 行号(从1开始)
|
||||
|
||||
@Min(1)
|
||||
private int colNum; // 列号(从1开始)
|
||||
|
||||
@NotBlank
|
||||
private String newValue;
|
||||
}
|
@ -2,10 +2,7 @@ package com.yfd.platform.modules.experimentalData.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.yfd.platform.config.ResponseResult;
|
||||
import com.yfd.platform.modules.experimentalData.domain.DualTreeResponse;
|
||||
import com.yfd.platform.modules.experimentalData.domain.MoveCopyFileFolderRequest;
|
||||
import com.yfd.platform.modules.experimentalData.domain.Parameter;
|
||||
import com.yfd.platform.modules.experimentalData.domain.TsFiles;
|
||||
import com.yfd.platform.modules.experimentalData.domain.*;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@ -170,12 +167,18 @@ public interface ITsFilesService extends IService<TsFiles> {
|
||||
*/
|
||||
String readFileContent(String id) throws IOException;
|
||||
|
||||
/**
|
||||
* 保存文件内容接口
|
||||
*
|
||||
* @param id 文件的id
|
||||
* @param content 新的文件内容(HTML/文本)
|
||||
* @return 操作结果
|
||||
*/
|
||||
/**********************************
|
||||
* 用途说明: 保存文件内容接口
|
||||
* 参数说明 id 文件的ID
|
||||
* 参数说明 content 新的文件内容(HTML/文本)
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult操作结果
|
||||
***********************************/
|
||||
void saveFileContent(String id, String content) throws IOException;
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 批量修改文件中多行多列的内容
|
||||
* 参数说明 request 要修改的文件信息
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult操作结果
|
||||
***********************************/
|
||||
void batchUpdateFile(String id, List<ModifyCommand> modifications) throws IOException;
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package com.yfd.platform.modules.experimentalData.service.impl;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
|
||||
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
@ -24,6 +26,9 @@ import com.amazonaws.services.s3.model.S3ObjectInputStream;
|
||||
import com.amazonaws.util.IOUtils;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.opencsv.CSVReader;
|
||||
import com.opencsv.CSVWriter;
|
||||
import com.opencsv.exceptions.CsvValidationException;
|
||||
import com.yfd.platform.component.ServerSendEventServer;
|
||||
import com.yfd.platform.config.ResponseResult;
|
||||
import com.yfd.platform.modules.experimentalData.domain.*;
|
||||
@ -62,7 +67,7 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value; // 正确
|
||||
import javax.annotation.Resource;
|
||||
import javax.xml.crypto.Data;
|
||||
import java.io.*;
|
||||
@ -108,6 +113,8 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
private List<String> compressSuffixes;
|
||||
private final Set<String> addedEntries = new HashSet<>();
|
||||
|
||||
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 分页查询试验数据管理-文档内容
|
||||
* 参数说明
|
||||
@ -4263,6 +4270,144 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 批量修改文件中多行多列的内容
|
||||
* 参数说明 request 要修改的文件信息
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult操作结果
|
||||
***********************************/
|
||||
@Override
|
||||
public void batchUpdateFile(String id, List<ModifyCommand> modifications)throws IOException {
|
||||
StorageSourceConfig config = storageSourceConfigMapper.selectOne(new QueryWrapper<StorageSourceConfig>().eq("name", "filePath"));
|
||||
TsFiles tsFile = tsFilesMapper.selectById(id);
|
||||
if (tsFile == null) {
|
||||
throw new IllegalArgumentException("文件ID不存在: " + id);
|
||||
}
|
||||
Path filePath = Paths.get(config.getValue(), tsFile.getWorkPath(), tsFile.getFileName()).normalize();
|
||||
// 安全校验
|
||||
if (!filePath.startsWith(config.getValue())) {
|
||||
throw new SecurityException("路径越界: " + filePath);
|
||||
}
|
||||
|
||||
// 1.2 检查文件是否为文本类型
|
||||
validateTextFile(filePath);
|
||||
|
||||
LOGGER.info("批量修改文件: {}, 修改指令数: {}", filePath, modifications.size());
|
||||
|
||||
|
||||
// 3. 创建临时文件(在指定目录下)
|
||||
Path tempDir = Paths.get(config.getValue(), tsFile.getWorkPath()).normalize();
|
||||
if (!Files.exists(tempDir)) {
|
||||
Files.createDirectories(tempDir); // 确保目录存在
|
||||
}
|
||||
|
||||
// 临时文件名格式:原文件名_时间戳.tmp
|
||||
String tempFileName = tsFile.getFileName() + "_" + System.currentTimeMillis() + ".tmp";
|
||||
Path tempPath = tempDir.resolve(tempFileName);
|
||||
|
||||
try {
|
||||
// 读取文件内容(兼容Java 8)
|
||||
List<String> lines = new ArrayList<>();
|
||||
try (BufferedReader reader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8)) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
lines.add(line);
|
||||
}
|
||||
}
|
||||
|
||||
applyModifications(lines, modifications);
|
||||
|
||||
// 写入临时文件(兼容Java 8)
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(tempPath, StandardCharsets.UTF_8)) {
|
||||
for (String line : lines) {
|
||||
writer.write(line);
|
||||
writer.newLine(); // 保留原换行符风格
|
||||
}
|
||||
}
|
||||
|
||||
Files.move(tempPath, filePath, StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (Exception e) {
|
||||
Files.deleteIfExists(tempPath);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 应用所有修改到文件内容
|
||||
* @param lines 文件每一行的内容
|
||||
* @param modifications 修改指令集合
|
||||
*/
|
||||
private void applyModifications(List<String> lines, List<ModifyCommand> modifications) {
|
||||
modifications.forEach(cmd -> {
|
||||
if (cmd.getLineNum() > lines.size()) {
|
||||
throw new IllegalArgumentException("行号超出范围: " + cmd.getLineNum());
|
||||
}
|
||||
String originalLine = lines.get(cmd.getLineNum() - 1);
|
||||
String modifiedLine = modifyLine(originalLine, cmd.getColNum(), cmd.getNewValue());
|
||||
lines.set(cmd.getLineNum() - 1, modifiedLine);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void validateTextFile(Path filePath) throws IOException {
|
||||
String mimeType = Files.probeContentType(filePath);
|
||||
if (mimeType == null || !mimeType.startsWith("text/")) {
|
||||
throw new IOException("只允许修改文本文件,检测到类型: " + mimeType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String modifyTabDelimitedLine(String line, int colNum, String newValue) {
|
||||
String[] columns = line.split("\t", -1); // -1保留空列
|
||||
if (colNum < 1 || colNum > columns.length) {
|
||||
throw new IllegalArgumentException("列号越界: " + colNum);
|
||||
}
|
||||
columns[colNum - 1] = newValue;
|
||||
return String.join("\t", columns);
|
||||
}
|
||||
|
||||
private String modifyCsvLine(String line, int colNum, String newValue) {
|
||||
try (CSVReader reader = new CSVReader(new StringReader(line))) {
|
||||
String[] columns = reader.readNext();
|
||||
if (colNum < 1 || colNum > columns.length) {
|
||||
throw new IllegalArgumentException("列号越界: " + colNum);
|
||||
}
|
||||
columns[colNum - 1] = newValue;
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
try (CSVWriter writer = new CSVWriter(sw)) {
|
||||
writer.writeNext(columns);
|
||||
return sw.toString().trim(); // 去除末尾换行
|
||||
}
|
||||
} catch (IOException | CsvValidationException e) {
|
||||
throw new UncheckedIOException("CSV解析失败", (IOException) e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String modifySpaceDelimitedLine(String line, int colNum, String newValue) {
|
||||
// 处理连续多个空格(保留原始对齐)
|
||||
String[] columns = line.split("\\s+", -1);
|
||||
if (colNum < 1 || colNum > columns.length) {
|
||||
throw new IllegalArgumentException("列号越界: " + colNum);
|
||||
}
|
||||
columns[colNum - 1] = newValue;
|
||||
|
||||
// 重建原始空格对齐(假设原文件用固定空格数分隔)
|
||||
return String.join(" ", columns); // 用4个空格分隔
|
||||
}
|
||||
|
||||
private String modifyLine(String line, int colNum, String newValue) {
|
||||
// 自动检测分隔符类型
|
||||
if (line.contains("\t")) {
|
||||
return modifyTabDelimitedLine(line, colNum, newValue);
|
||||
} else if (line.contains(",")) {
|
||||
return modifyCsvLine(line, colNum, newValue);
|
||||
} else {
|
||||
return modifySpaceDelimitedLine(line, colNum, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user