{"record":{"id":"abf7604174208c2b","repo":"jeecgboot/JeecgBoot","slug":"specified-file-not-found","errorCode":null,"errorMessage":"Specified file not found","messagePattern":"Specified file not found","errorType":"exception","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/FileDownloadUtils.java","lineNumber":47,"sourceCode":" * @date: 2019-05-24 16:34\n **/\n@Slf4j\npublic class FileDownloadUtils {\n\n    /**\n     * 单文件下载\n     *\n     * @param response\n     * @param storePath 下载文件储存地址\n     * @param fileName  文件名称\n     * @author: chenrui\n     * @date: 2019/5/24 17:10\n     */\n    public static void downloadFile(HttpServletResponse response, String storePath, String fileName) {\n        response.setCharacterEncoding(\"UTF-8\");\n        File file = new File(storePath);\n        if (!file.exists()) {\n            throw new NullPointerException(\"Specified file not found\");\n        }\n        if (fileName == null || fileName.isEmpty()) {\n            throw new NullPointerException(\"The file name can not null\");\n        }\n        // 配置文件下载\n        response.setHeader(\"content-type\", \"application/octet-stream\");\n        response.setContentType(\"application/octet-stream\");\n        // 下载文件能正常显示中文\n        try {\n            response.setHeader(\"Content-Disposition\", \"attachment;filename=\" + URLEncoder.encode(fileName, \"UTF-8\"));\n            response.setHeader(\"Access-Control-Expose-Headers\", \"Content-Disposition\");\n        } catch (UnsupportedEncodingException e) {\n            log.error(e.getMessage(), e);\n        }\n        // 实现文件下载\n        byte[] buffer = new byte[1024];\n        try (FileInputStream fis = new FileInputStream(file);\n             BufferedInputStream bis = new BufferedInputStream(fis);) {","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/FileDownloadUtils.java#L29-L65","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before — download endpoint trusts DB path blindly\ndownloadFile(response, record.getStorePath(), record.getFileName());\n\n// after — verify existence, return clean 404\nFile f = new File(record.getStorePath());\nif (!f.exists()) { response.sendError(404, \"file gone\"); return; }\ndownloadFile(response, record.getStorePath(), record.getFileName());","handlingStrategy":"validation","validationCode":"// Check existence and return a clean 404 instead of NPE\nFile f = new File(storePath);\nif (!f.exists() || !f.isFile()) {\n  response.sendError(HttpServletResponse.SC_NOT_FOUND, \"File not found\");\n  return;\n}\nFileDownloadUtils.downloadFile(response, storePath, fileName);","typeGuard":"public static boolean isDownloadable(String storePath) {\n  File f = new File(storePath);\n  return f.exists() && f.isFile() && f.canRead();\n}","tryCatchPattern":"try {\n  FileDownloadUtils.downloadFile(response, storePath, fileName);\n} catch (NullPointerException e) {\n  response.sendError(404, \"Specified file not found\");\n}","preventionTips":["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."],"tags":["backend","file-download","io","jeecg"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}