From d008278b6a19746fc2e4bdc014bc56a874efb218 Mon Sep 17 00:00:00 2001 From: gaoxq <376340421@qq.com> Date: Fri, 3 Apr 2026 22:33:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AE=9A=E6=97=B6=E6=B8=85?= =?UTF-8?q?=E7=90=86=E5=9B=9E=E6=94=B6=E7=AB=99=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/GlobalExceptionHandler.java | 39 ++++++++++++++++++- web-vue/src/api/request.js | 14 ++++++- web-vue/src/views/files/index.vue | 36 +++++++++++------ 3 files changed, 75 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/filesystem/config/GlobalExceptionHandler.java b/src/main/java/com/filesystem/config/GlobalExceptionHandler.java index a44b76b..fa13131 100644 --- a/src/main/java/com/filesystem/config/GlobalExceptionHandler.java +++ b/src/main/java/com/filesystem/config/GlobalExceptionHandler.java @@ -2,22 +2,59 @@ package com.filesystem.config; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.multipart.MaxUploadSizeExceededException; import java.io.IOException; +import java.util.HashMap; import java.util.Map; +import java.util.stream.Collectors; @RestControllerAdvice public class GlobalExceptionHandler { + /** + * 处理文件上传大小超限异常 + */ + @ExceptionHandler(MaxUploadSizeExceededException.class) + public ResponseEntity handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) { + return ResponseEntity.status(HttpStatus.PAYLOAD_TOO_LARGE) + .body(Map.of("message", "文件大小超过限制,单次上传总大小不能超过500MB")); + } + + /** + * 处理参数校验异常 + */ + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity handleValidationException(MethodArgumentNotValidException e) { + String errorMsg = e.getBindingResult().getFieldErrors().stream() + .map(FieldError::getDefaultMessage) + .collect(Collectors.joining(", ")); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("message", errorMsg.isEmpty() ? "参数校验失败" : errorMsg)); + } + + /** + * 处理非法参数异常 + */ + @ExceptionHandler(IllegalArgumentException.class) + public ResponseEntity handleIllegalArgumentException(IllegalArgumentException e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("message", e.getMessage() != null ? e.getMessage() : "参数错误")); + } + /** * 处理所有运行时异常 */ @ExceptionHandler(RuntimeException.class) public ResponseEntity handleRuntimeException(RuntimeException e) { e.printStackTrace(); - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + // 业务异常返回 400,避免触发前端登录跳转 + HttpStatus status = HttpStatus.BAD_REQUEST; + return ResponseEntity.status(status) .body(Map.of("message", e.getMessage() != null ? e.getMessage() : "服务器内部错误")); } diff --git a/web-vue/src/api/request.js b/web-vue/src/api/request.js index bd5a6ca..efa440e 100644 --- a/web-vue/src/api/request.js +++ b/web-vue/src/api/request.js @@ -36,6 +36,7 @@ request.interceptors.response.use( } const status = error.response?.status + const errorMsg = error.response?.data?.message || error.message || '请求失败' // 只有 401/403 才清理 token 并跳转登录页 // 但在登录页时不跳转(避免死循环),登录接口的 401 也不跳转 @@ -57,9 +58,20 @@ request.interceptors.response.use( localStorage.removeItem('storageLimit') window.location.href = '/login' + return Promise.reject(error) } - return Promise.reject(error) + // 413 文件过大,返回带消息的错误 + if (status === 413) { + const err = new Error(errorMsg) + err.response = error.response + return Promise.reject(err) + } + + // 其他错误,返回带消息的错误 + const err = new Error(errorMsg) + err.response = error.response + return Promise.reject(err) } ) diff --git a/web-vue/src/views/files/index.vue b/web-vue/src/views/files/index.vue index 3f1b4c3..c491f52 100644 --- a/web-vue/src/views/files/index.vue +++ b/web-vue/src/views/files/index.vue @@ -389,7 +389,8 @@ const handleUpload = async (fileList) => { loadFiles() refreshStorage() } catch (e) { - ElMessage.error('上传失败') + const errorMsg = e.response?.data?.message || e.message || '上传失败' + ElMessage.error(errorMsg) } finally { uploading.value = false } @@ -401,7 +402,8 @@ const handleCreateFolder = async (name) => { ElMessage.success('创建成功') loadFiles() } catch (e) { - ElMessage.error('创建失败') + const errorMsg = e.response?.data?.message || e.message || '创建失败' + ElMessage.error(errorMsg) } } @@ -445,7 +447,8 @@ const handleConfirmRename = async ({ id, name }) => { ElMessage.success('重命名成功') loadFiles() } catch (e) { - ElMessage.error('重命名失败') + const errorMsg = e.response?.data?.message || e.message || '重命名失败' + ElMessage.error(errorMsg) } } @@ -459,7 +462,8 @@ const handleDownload = async (file) => { a.click() URL.revokeObjectURL(url) } catch (e) { - ElMessage.error('下载失败') + const errorMsg = e.response?.data?.message || e.message || '下载失败' + ElMessage.error(errorMsg) } } @@ -482,7 +486,8 @@ const handleRestore = async (file) => { ElMessage.success('已还原') loadFiles() } catch (e) { - ElMessage.error('还原失败') + const errorMsg = e.response?.data?.message || e.message || '还原失败' + ElMessage.error(errorMsg) } } @@ -494,7 +499,8 @@ const handleDeletePermanently = async (file) => { loadFiles() refreshStorage() } catch (e) { - ElMessage.error('删除失败') + const errorMsg = e.response?.data?.message || e.message || '删除失败' + ElMessage.error(errorMsg) } } @@ -506,7 +512,8 @@ const handleEmptyTrash = async () => { loadFiles() refreshStorage() } catch (e) { - ElMessage.error('操作失败') + const errorMsg = e.response?.data?.message || e.message || '操作失败' + ElMessage.error(errorMsg) } } @@ -524,7 +531,8 @@ const handleConfirmShare = async ({ users, permission }) => { ElMessage.success('共享成功') loadFiles() } catch (e) { - ElMessage.error('共享失败') + const errorMsg = e.response?.data?.message || e.message || '共享失败' + ElMessage.error(errorMsg) } } @@ -535,7 +543,8 @@ const handleCancelShare = async (file) => { ElMessage.success('已取消共享') loadFiles() } catch (e) { - ElMessage.error('操作失败') + const errorMsg = e.response?.data?.message || e.message || '操作失败' + ElMessage.error(errorMsg) } } @@ -608,7 +617,8 @@ const handleBatchMove = async () => { movableFolders.value = res.data || [] batchMoveVisible.value = true } catch (e) { - ElMessage.error('获取目录列表失败') + const errorMsg = e.response?.data?.message || e.message || '获取目录列表失败' + ElMessage.error(errorMsg) } } @@ -701,7 +711,8 @@ const handleBatchCancelShare = async () => { selectedFiles.value = [] loadFiles() } catch (e) { - ElMessage.error('操作失败') + const errorMsg = e.response?.data?.message || e.message || '操作失败' + ElMessage.error(errorMsg) } } @@ -719,7 +730,8 @@ const handleBatchRestore = async () => { loadFiles() refreshStorage() } catch (e) { - ElMessage.error('操作失败') + const errorMsg = e.response?.data?.message || e.message || '操作失败' + ElMessage.error(errorMsg) } }