YunaiV/yudao-cloud · warning · IllegalArgumentException
结尾的 path 路径必须传递
Error message
结尾的 path 路径必须传递
What it means
FileController.getFileContent maps GET /{configId}/get/** and extracts everything after '/get/' as the file path; if that substring is empty (request URI ends exactly at '/get/' — Spring still matches the /** wildcard), it throws IllegalArgumentException demanding the trailing path. The path is later URL-decoded, so a fully-encoded empty path also fails here.
Source
Thrown at yudao-module-infra/yudao-module-infra-server/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java:112
@Parameter(name = "ids", description = "编号列表", required = true)
@PreAuthorize("@ss.hasPermission('infra:file:delete')")
public CommonResult<Boolean> deleteFileList(@RequestParam("ids") List<Long> ids) throws Exception {
fileService.deleteFileList(ids);
return success(true);
}
@GetMapping("/{configId}/get/**")
@PermitAll
@TenantIgnore
@Operation(summary = "下载文件")
@Parameter(name = "configId", description = "配置编号", required = true)
public void getFileContent(HttpServletRequest request,
HttpServletResponse response,
@PathVariable("configId") Long configId) throws Exception {
// 获取请求的路径
String path = StrUtil.subAfter(request.getRequestURI(), "/get/", false);
if (StrUtil.isEmpty(path)) {
throw new IllegalArgumentException("结尾的 path 路径必须传递");
}
// 解码,解决中文、%、+ 等特殊字符路径的问题
// https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/807/
// https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1432/
path = HttpUtils.decodeUrlPath(path);
// 读取内容
byte[] content = fileService.getFileContent(configId, path);
if (content == null) {
log.warn("[getFileContent][configId({}) path({}) 文件不存在]", configId, path);
response.setStatus(HttpStatus.NOT_FOUND.value());
return;
}
FileDO file = fileService.getFileByConfigIdAndPath(configId, path);
String filename = file != null && StrUtil.isNotEmpty(file.getName()) ? file.getName() : FileUtil.getName(path);
writeAttachment(response, filename, content);
}
View on GitHub (pinned to 477be9dd49)
Solutions
- Append the actual file path after /get/: /admin-api/infra/file/{configId}/get/2024/08/avatar.png
- Check the stored file URL/path field is non-empty before building the link
- URL-encode the path properly (Chinese, %, +) so it survives proxies
Example fix
// before
window.open(`/admin-api/infra/file/${configId}/get/`); // empty path
// after
window.open(`/admin-api/infra/file/${configId}/get/${encodeURIComponent(filePath)}`); Defensive patterns
Strategy: validation
Validate before calling
String path = StrUtil.subAfter(request.getRequestURI(), "/get/", false);
if (StrUtil.isEmpty(path)) {
response.setStatus(400);
return;
} Prevention
- Never build download URLs from unchecked DB path fields — skip when empty
- URL-encode the file path segment (Chinese, %, +)
- Probe with a HEAD/GET and treat 400/404 as 'file not set' rather than crashing the UI
When it happens
Trigger: GET /admin-api/infra/file/{configId}/get/ with nothing after the slash; URL truncated by a client that strips a trailing slash's content (path ends '/get/'); constructing the URL from a null/empty file path variable.
Common situations: Template building the download URL from a DB field that is null/empty (e.g. avatar not yet uploaded); reverse proxy or frontend router normalizing away the path segment; manual testing hitting the bare endpoint.
Related errors
AI-assisted analysis of YunaiV/yudao-cloud@477be9dd49 (2026-08-14).
Data as JSON: /api/errors/956a8d6b3117ac1d.
Report an issue: GitHub.