更新数据同步
This commit is contained in:
@@ -12,6 +12,7 @@ import com.mini.capi.model.info.TodoHandleDTO;
|
|||||||
import com.mini.capi.utils.FileUtils;
|
import com.mini.capi.utils.FileUtils;
|
||||||
import com.mini.capi.utils.vId;
|
import com.mini.capi.utils.vId;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@@ -37,7 +38,7 @@ public class workController {
|
|||||||
@Resource
|
@Resource
|
||||||
private BizFilesService bizFilesService;
|
private BizFilesService bizFilesService;
|
||||||
|
|
||||||
private static String UPLOAD_PATH = "/ogsapp/files/";
|
private static final String UPLOAD_PATH = "/ogsapp/files/";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,7 +70,7 @@ public class workController {
|
|||||||
/**
|
/**
|
||||||
* 创建文件夹
|
* 创建文件夹
|
||||||
*/
|
*/
|
||||||
@PostMapping("/CreateFolder")
|
@PostMapping("/createFolder")
|
||||||
public ApiResult<?> CreateFolder(@Validated @RequestBody CreateFolder request) {
|
public ApiResult<?> CreateFolder(@Validated @RequestBody CreateFolder request) {
|
||||||
try {
|
try {
|
||||||
String dirId = vId.getCid();
|
String dirId = vId.getCid();
|
||||||
@@ -104,6 +105,7 @@ public class workController {
|
|||||||
try {
|
try {
|
||||||
// 1. 获取原始文件名和后缀
|
// 1. 获取原始文件名和后缀
|
||||||
String originalFilename = file.getOriginalFilename();
|
String originalFilename = file.getOriginalFilename();
|
||||||
|
String fileType = FilenameUtils.getExtension(originalFilename);
|
||||||
String fileSuffix = originalFilename.substring(originalFilename.lastIndexOf("."));
|
String fileSuffix = originalFilename.substring(originalFilename.lastIndexOf("."));
|
||||||
// 2. 生成唯一文件名(避免文件名冲突)
|
// 2. 生成唯一文件名(避免文件名冲突)
|
||||||
String uniqueFileName = vId.getCid() + fileSuffix;
|
String uniqueFileName = vId.getCid() + fileSuffix;
|
||||||
@@ -114,7 +116,7 @@ public class workController {
|
|||||||
bizFiles.setFileName(originalFilename);
|
bizFiles.setFileName(originalFilename);
|
||||||
bizFiles.setFolderId(folderId);
|
bizFiles.setFolderId(folderId);
|
||||||
bizFiles.setFileSize(file.getSize());
|
bizFiles.setFileSize(file.getSize());
|
||||||
bizFiles.setFileType(fileSuffix);
|
bizFiles.setFileType(fileType);
|
||||||
bizFiles.setFilePath(filePath.toString());
|
bizFiles.setFilePath(filePath.toString());
|
||||||
bizFiles.setCreatorId(0);
|
bizFiles.setCreatorId(0);
|
||||||
bizFiles.setIsDeleted(0);
|
bizFiles.setIsDeleted(0);
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javasc
|
|||||||
server.tomcat.max-connections=200
|
server.tomcat.max-connections=200
|
||||||
server.tomcat.threads.max=100
|
server.tomcat.threads.max=100
|
||||||
server.tomcat.threads.min-spare=10
|
server.tomcat.threads.min-spare=10
|
||||||
|
spring.servlet.multipart.enabled=true
|
||||||
|
spring.servlet.multipart.max-file-size=200MB
|
||||||
|
spring.servlet.multipart.max-request-size=1000MB
|
||||||
|
spring.servlet.multipart.file-size-threshold=10MB
|
||||||
## Token
|
## Token
|
||||||
security.default-token=3774e79ac55aff6d1afc0f94bfaf131d
|
security.default-token=3774e79ac55aff6d1afc0f94bfaf131d
|
||||||
## MySQL
|
## MySQL
|
||||||
|
|||||||
@@ -468,7 +468,7 @@
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// 实际项目中,这里应该调用后端API创建文件夹
|
// 实际项目中,这里应该调用后端API创建文件夹
|
||||||
// 例如:
|
// 例如:
|
||||||
fetch('CreateFolder', {
|
fetch('createFolder', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -582,74 +582,118 @@
|
|||||||
showMessage('请先选择要上传的文件', 'error');
|
showMessage('请先选择要上传的文件', 'error');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 前端文件大小校验(和后端max-file-size一致,可选)
|
||||||
|
const MAX_FILE_SIZE = 200 * 1024 * 1024; // 200MB(字节)
|
||||||
|
const overSizeFile = uploadFiles.find(file => file.size > MAX_FILE_SIZE);
|
||||||
|
if (overSizeFile) {
|
||||||
|
showMessage(`文件 ${overSizeFile.name} 超过 200MB 限制,请压缩后上传`, 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const uploadFolder = document.getElementById('uploadFolder').value;
|
const uploadFolder = document.getElementById('uploadFolder').value;
|
||||||
showMessage(`正在上传 ${uploadFiles.length} 个文件...`);
|
showMessage(`正在上传 ${uploadFiles.length} 个文件...`);
|
||||||
|
|
||||||
// 禁用上传按钮
|
|
||||||
const uploadBtn = document.getElementById('startUploadBtn');
|
const uploadBtn = document.getElementById('startUploadBtn');
|
||||||
uploadBtn.disabled = true;
|
uploadBtn.disabled = true;
|
||||||
uploadBtn.innerHTML = '<i class="fa fa-spinner fa-spin mr-2"></i> 上传中...';
|
uploadBtn.innerHTML = '<i class="fa fa-spinner fa-spin mr-2"></i> 上传中...';
|
||||||
|
|
||||||
// 显示进度条
|
|
||||||
const progressBars = document.querySelectorAll('.upload-progress');
|
const progressBars = document.querySelectorAll('.upload-progress');
|
||||||
progressBars.forEach(bar => {
|
progressBars.forEach(bar => {
|
||||||
bar.classList.remove('hidden');
|
bar.classList.remove('hidden');
|
||||||
});
|
});
|
||||||
|
|
||||||
// 模拟上传进度
|
let processedFiles = 0; // 统计「已处理完成」的文件数(成功+失败)
|
||||||
let completedFiles = 0;
|
let successCount = 0; // 统计成功数
|
||||||
|
const failedFiles = []; // 记录失败文件名
|
||||||
|
|
||||||
uploadFiles.forEach((file, index) => {
|
uploadFiles.forEach((file, index) => {
|
||||||
simulateUploadProgress(index, file, () => {
|
uploadSingleFile(file, index, uploadFolder,
|
||||||
completedFiles++;
|
// 单个文件处理完成后的回调(无论成功/失败)
|
||||||
// 检查是否所有文件都上传完成
|
(isSuccess) => {
|
||||||
if (completedFiles === uploadFiles.length) {
|
processedFiles++;
|
||||||
setTimeout(() => {
|
if (isSuccess) successCount++;
|
||||||
// 启用上传按钮
|
else failedFiles.push(file.name);
|
||||||
|
|
||||||
|
// 关键:所有文件都处理完成后,再关闭模态框
|
||||||
|
if (processedFiles === uploadFiles.length) {
|
||||||
uploadBtn.disabled = false;
|
uploadBtn.disabled = false;
|
||||||
uploadBtn.innerHTML = '开始上传';
|
uploadBtn.innerHTML = '开始上传';
|
||||||
// 实际项目中,这里应该调用后端API上传文件
|
|
||||||
// 例如:
|
// 关闭模态框(核心位置:所有文件处理完后)
|
||||||
const formData = new FormData();
|
closeUploadFileModal();
|
||||||
uploadFiles.forEach(file => {
|
|
||||||
formData.append('files', file);
|
// 显示最终结果
|
||||||
});
|
let message = '';
|
||||||
formData.append('folderId', uploadFolder);
|
if (successCount === uploadFiles.length) {
|
||||||
fetch('uploadFiles', {
|
message = `全部 ${successCount} 个文件上传成功`;
|
||||||
method: 'POST',
|
window.location.href = 'dataDoc'; // 全部成功才跳转
|
||||||
body: formData,
|
} else if (successCount > 0) {
|
||||||
})
|
message = `上传完成:成功 ${successCount} 个,失败 ${failedFiles.length} 个(失败:${failedFiles.join('、')})`;
|
||||||
.then(response => response.json())
|
} else {
|
||||||
.then(data => {
|
message = `全部 ${failedFiles.length} 个文件上传失败(${failedFiles.join('、')})`;
|
||||||
// 处理上传成功
|
}
|
||||||
closeUploadFileModal();
|
showMessage(message, failedFiles.length > 0 ? 'error' : 'success');
|
||||||
// 显示成功消息
|
}
|
||||||
showMessage(`${completedFiles} 个文件上传成功`);
|
|
||||||
window.location.href = 'dataDoc'
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
// 处理上传失败
|
|
||||||
showMessage('上传文件失败', 'error');
|
|
||||||
});
|
|
||||||
}, 500);
|
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 模拟上传进度
|
// 单个文件上传(补充回调参数isSuccess,标记是否成功)
|
||||||
function simulateUploadProgress(index, file, callback) {
|
function uploadSingleFile(file, index, folderId, callback) {
|
||||||
const progressBar = document.querySelectorAll('.upload-progress-bar')[index];
|
const progressBar = document.querySelectorAll('.upload-progress-bar')[index];
|
||||||
let progress = 0;
|
const formData = new FormData();
|
||||||
|
formData.append('files', file);
|
||||||
|
formData.append('folderId', folderId);
|
||||||
|
|
||||||
const interval = setInterval(() => {
|
const xhr = new XMLHttpRequest();
|
||||||
progress += Math.random() * 20;
|
xhr.open('POST', 'uploadFiles', true);
|
||||||
if (progress >= 100) {
|
xhr.withCredentials = true;
|
||||||
progress = 100;
|
xhr.timeout = 300000; // 5分钟超时
|
||||||
clearInterval(interval);
|
|
||||||
setTimeout(callback, 500);
|
xhr.upload.onprogress = (e) => {
|
||||||
|
if (e.lengthComputable) {
|
||||||
|
const progress = (e.loaded / e.total) * 100;
|
||||||
|
progressBar.style.width = `${progress.toFixed(2)}%`;
|
||||||
}
|
}
|
||||||
progressBar.style.width = `${progress}%`;
|
};
|
||||||
}, 200);
|
|
||||||
|
xhr.onload = () => {
|
||||||
|
if (xhr.status >= 200 && xhr.status < 300) {
|
||||||
|
let data;
|
||||||
|
try {
|
||||||
|
data = JSON.parse(xhr.responseText);
|
||||||
|
} catch (err) {
|
||||||
|
showMessage(`文件 ${file.name} 上传成功,但后端返回格式错误`, 'warning');
|
||||||
|
progressBar.style.width = '100%';
|
||||||
|
callback(true); // 格式错误仍算上传成功(可根据需求调整)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data.success) {
|
||||||
|
progressBar.style.width = '100%';
|
||||||
|
callback(true); // 成功:回调传true
|
||||||
|
} else {
|
||||||
|
showMessage(`文件 ${file.name} 上传失败:${data.message}`, 'error');
|
||||||
|
callback(false); // 失败:回调传false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showMessage(`文件 ${file.name} 上传失败:状态码 ${xhr.status}`, 'error');
|
||||||
|
callback(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onerror = () => {
|
||||||
|
showMessage(`文件 ${file.name} 网络错误`, 'error');
|
||||||
|
callback(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.ontimeout = () => {
|
||||||
|
showMessage(`文件 ${file.name} 上传超时`, 'error');
|
||||||
|
callback(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.send(formData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 格式化文件大小
|
// 格式化文件大小
|
||||||
|
|||||||
Reference in New Issue
Block a user