elunez/eladmin · error · BadRequestException

上传失败

Error message

上传失败

What it means

Thrown by LocalStorageServiceImpl.create when FileUtil.upload(multipartFile, path) returns null after the size check passed — hutool's FileUtil.upload returns null on IOException while writing the multipart file to disk under properties.getPath().getPath() + type + separator. So the file exceeded maxSize it would have thrown earlier (a different exception); this specific error means a disk-level write failure.

Source

Thrown at eladmin-tools/src/main/java/me/zhengjie/service/impl/LocalStorageServiceImpl.java:80

        return localStorageMapper.toDto(localStorageRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    public LocalStorageDto findById(Long id){
        LocalStorage localStorage = localStorageRepository.findById(id).orElseGet(LocalStorage::new);
        ValidationUtil.isNull(localStorage.getId(),"LocalStorage","id",id);
        return localStorageMapper.toDto(localStorage);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LocalStorage create(String name, MultipartFile multipartFile) {
        FileUtil.checkSize(properties.getMaxSize(), multipartFile.getSize());
        String suffix = FileUtil.getExtensionName(multipartFile.getOriginalFilename());
        String type = FileUtil.getFileType(suffix);
        File file = FileUtil.upload(multipartFile, properties.getPath().getPath() + type +  File.separator);
        if(ObjectUtil.isNull(file)){
            throw new BadRequestException("上传失败");
        }
        try {
            name = StringUtils.isBlank(name) ? FileUtil.getFileNameNoEx(multipartFile.getOriginalFilename()) : name;
            LocalStorage localStorage = new LocalStorage(
                    file.getName(),
                    name,
                    suffix,
                    file.getPath(),
                    type,
                    FileUtil.getSize(multipartFile.getSize())
            );
            return localStorageRepository.save(localStorage);
        }catch (Exception e){
            FileUtil.del(file);
            throw e;
        }
    }

View on GitHub (pinned to 55fbf70595)

Solutions

  1. Check the configured storage path (LocalStorage properties, e.g. files.path in application.yml) exists and is writable by the JVM process user (touch test).
  2. Free disk space / raise quota if the volume is full (df -h).
  3. In containers, mount a writable volume at the configured path and ensure the run user owns it.
  4. Confirm directory creation: FileUtil.upload expects the base type directories to be creatable — pre-create `<path>/image`, `<path>/doc`, etc. or grant mkdir rights.
  5. Inspect logs for the underlying IOException swallowed by FileUtil.upload's null return.

Example fix

// before
File file = FileUtil.upload(multipartFile, properties.getPath().getPath() + type + File.separator);
if(ObjectUtil.isNull(file)){
    throw new BadRequestException("上传失败");
}

// after: write explicitly and fail with the real cause
File dir = new File(properties.getPath().getPath(), type);
if(!dir.exists() && !dir.mkdirs()){
    throw new BadRequestException("存储目录创建失败: " + dir.getAbsolutePath());
}
File file = null;
try {
    file = new File(dir, IdUtil.simpleUUID() + "." + suffix);
    multipartFile.transferTo(file);
} catch (IOException e) {
    throw new BadRequestException("上传失败: " + e.getMessage());
}
Defensive patterns

Strategy: validation

Validate before calling

// startup sanity: storage root must be writable
File root = new File(properties.getPath().getPath());
if (!root.exists() && !root.mkdirs()) throw new IllegalStateException("storage path not creatable: " + root);
if (!root.canWrite()) throw new IllegalStateException("storage path not writable: " + root);

Try / catch

try { localStorageService.create(name, file); } catch (BadRequestException e) { if ("上传失败".equals(e.getMessage())) { /* disk/permission issue: check volume, do not retry the same upload blindly */ } }

Prevention

When it happens

Trigger: POST /localStorage (file upload) or POST /localStorage/pictures where the target directory configured by LocalStorage properties (files.path) does not exist or is not writable; disk full; container read-only filesystem; path with insufficient permissions for the JVM user.

Common situations: Default './file' path not created in the deployment dir; Docker image running as non-root with no write access to the mounted volume; disk quota exhausted; SELinux denying writes; path property changed to a location that isn't mounted.

Related errors


AI-assisted analysis of elunez/eladmin@55fbf70595 (2026-08-14). Data as JSON: /api/errors/d21e28fce7eea0aa. Report an issue: GitHub.