elunez/eladmin · warning · BadRequestException

文件不存在或已被删除

Error message

文件不存在或已被删除

What it means

Thrown by S3StorageServiceImpl.privateDownload when s3StorageRepository.findById(id) returns empty — the requested file record is not in the database (never existed or already deleted). It fails before any S3 call, distinguishing a metadata miss from an S3-side error (errors 94/95).

Source

Thrown at eladmin-tools/src/main/java/me/zhengjie/service/impl/S3StorageServiceImpl.java:179

            map.put("文件名称", s3Storage.getFileName());
            map.put("真实存储的名称", s3Storage.getFileRealName());
            map.put("文件大小", s3Storage.getFileSize());
            map.put("文件MIME 类型", s3Storage.getFileMimeType());
            map.put("文件类型", s3Storage.getFileType());
            map.put("文件路径", s3Storage.getFilePath());
            map.put("创建者", s3Storage.getCreateBy());
            map.put("更新者", s3Storage.getUpdateBy());
            map.put("创建日期", s3Storage.getCreateTime());
            map.put("更新时间", s3Storage.getUpdateTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    public Map<String, String> privateDownload(Long id) {
        S3Storage storage = s3StorageRepository.findById(id).orElse(null);
        if (storage == null) {
            throw new BadRequestException("文件不存在或已被删除");
        }
        // 创建 GetObjectRequest,指定存储桶和文件键
        GetObjectRequest getObjectRequest = GetObjectRequest.builder()
                .bucket(amzS3Config.getDefaultBucket())
                .key(storage.getFilePath())
                .build();
        String base64Data;
        // 使用 try-with-resources 确保流能被自动关闭
        // s3Client.getObject() 返回一个 ResponseInputStream,它是一个包含S3对象数据的输入流
        try (ResponseInputStream<GetObjectResponse> s3InputStream = s3Client.getObject(getObjectRequest)) {
            // 使用 IOUtils.toByteArray 将输入流直接转换为字节数组
            byte[] fileBytes = IOUtils.toByteArray(s3InputStream);
            // 使用 Java 内置的 Base64 编码器将字节数组转换为 Base64 字符串
            base64Data = Base64.getEncoder().encodeToString(fileBytes);
        } catch (S3Exception e) {
            // 处理 AWS 特定的异常
            throw new BadRequestException("从 S3 下载文件时出错: " + e.awsErrorDetails().errorMessage());
        } catch (IOException e) {

View on GitHub (pinned to 55fbf70595)

Solutions

  1. Refresh the file list from the server and use a current id.
  2. If the record should exist, check the s3_storage table (was it deleted by a batch operation?).
  3. Handle the 400 gracefully in the UI with a 'file no longer available' state.
  4. For long-lived links, persist download requests server-side rather than raw ids.

Example fix

// before
S3Storage storage = s3StorageRepository.findById(id).orElse(null);
if (storage == null) {
    throw new BadRequestException("文件不存在或已被删除");
}

// after: use orElseThrow for the same behavior, less ceremony
S3Storage storage = s3StorageRepository.findById(id)
        .orElseThrow(() -> new BadRequestException("文件不存在或已被删除"));
Defensive patterns

Strategy: validation

Validate before calling

// caller-side existence check before requesting download
boolean exists = s3StorageRepository.existsById(id);
if (!exists) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body("文件不存在或已被删除"); }

Try / catch

try { s3StorageService.privateDownload(id); } catch (BadRequestException e) { if ("文件不存在或已被删除".equals(e.getMessage())) { /* refresh the file list; do not retry the same id */ } }

Prevention

When it happens

Trigger: GET the private-download endpoint with an id that isn't in s3_storage: stale UI list after another admin deleted files, hand-edited id, or a record removed by deleteAll while a user still had the row open.

Common situations: Frontend caching an old file list; concurrent deletion; bookmarked/download links persisted after cleanup jobs; id confusion between local storage and S3 storage tables.

Related errors


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