jeecgboot/JeecgBoot · error · NullPointerException
Specified file not found
Error message
Specified file not found
What it means
FileDownloadUtils.downloadFile constructs a File from storePath and checks exists() before streaming. If the file does not exist on disk, it throws NullPointerException('Specified file not found'). Notably it throws NPE (not FileNotFoundException) for a missing-file condition, which is an unusual exception-type choice that can confuse generic catch blocks. This is the single-file download entry point used by download endpoints.
Source
Thrown at jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/FileDownloadUtils.java:47
* @date: 2019-05-24 16:34
**/
@Slf4j
public class FileDownloadUtils {
/**
* 单文件下载
*
* @param response
* @param storePath 下载文件储存地址
* @param fileName 文件名称
* @author: chenrui
* @date: 2019/5/24 17:10
*/
public static void downloadFile(HttpServletResponse response, String storePath, String fileName) {
response.setCharacterEncoding("UTF-8");
File file = new File(storePath);
if (!file.exists()) {
throw new NullPointerException("Specified file not found");
}
if (fileName == null || fileName.isEmpty()) {
throw new NullPointerException("The file name can not null");
}
// 配置文件下载
response.setHeader("content-type", "application/octet-stream");
response.setContentType("application/octet-stream");
// 下载文件能正常显示中文
try {
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
} catch (UnsupportedEncodingException e) {
log.error(e.getMessage(), e);
}
// 实现文件下载
byte[] buffer = new byte[1024];
try (FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);) {View on GitHub (pinned to 96fb33f5ec)
Solutions
- Verify the file physically exists at the resolved storePath before calling downloadFile.
- Ensure storePath resolution (relative vs absolute, base directory) matches how the file was stored.
- In docker, confirm the upload volume is mounted to the same path in all containers.
- Add a file-exists check in the controller and return a 404 with a clear message instead of letting NPE propagate.
Example fix
// before — download endpoint trusts DB path blindly
downloadFile(response, record.getStorePath(), record.getFileName());
// after — verify existence, return clean 404
File f = new File(record.getStorePath());
if (!f.exists()) { response.sendError(404, "file gone"); return; }
downloadFile(response, record.getStorePath(), record.getFileName()); Defensive patterns
Strategy: validation
Validate before calling
// Check existence and return a clean 404 instead of NPE
File f = new File(storePath);
if (!f.exists() || !f.isFile()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, "File not found");
return;
}
FileDownloadUtils.downloadFile(response, storePath, fileName); Type guard
public static boolean isDownloadable(String storePath) {
File f = new File(storePath);
return f.exists() && f.isFile() && f.canRead();
} Try / catch
try {
FileDownloadUtils.downloadFile(response, storePath, fileName);
} catch (NullPointerException e) {
response.sendError(404, "Specified file not found");
} Prevention
- Validate file existence in the controller before delegating to downloadFile.
- Ensure storePath resolution matches the upload-time path scheme.
- Mount docker volumes consistently across containers.
When it happens
Trigger: A download request whose storePath points to a file that was deleted, never written, is on an unmounted volume, or whose path was constructed incorrectly (wrong base dir, missing subdirectory). Also when the file record exists in DB but the physical file was cleaned up.
Common situations: File was uploaded then the upload directory was migrated/cleaned; DB stores a relative path but storePath passed is absolute (or vice versa); docker volume not mounted in the container; file deleted manually but DB record remains.
Related errors
- The file name can not null
- 请注意,将要排序的列字段不存在:${column}
- 未获取到用户
- Illegal access to path outside of base directory.
- 非法业务路径,禁止访问上传目录之外的路径: ${bizPath}
AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14).
Data as JSON: /api/errors/abf7604174208c2b.
Report an issue: GitHub.