基于Spring Boot实现文件秒传的完整方案

发布于:2025-04-22 ⋅ 阅读:(20) ⋅ 点赞:(0)

精心整理了最新的面试资料和简历模板,有需要的可以自行获取

点击前往百度网盘获取
点击前往夸克网盘获取


一、什么是文件秒传?

文件秒传是指在文件上传场景中,当服务器已存在相同文件时,用户无需重复上传,系统通过校验文件唯一标识直接返回成功。关键技术点在于通过文件哈希值校验实现快速匹配。

二、技术实现原理

  1. 前端预处理

    • 计算文件哈希值(MD5/SHA-1/SHA-256)
    • 提交哈希值到服务端进行预检
  2. 服务端校验

    • 通过Redis或数据库查询哈希值是否存在
    • 存在则直接返回已上传文件地址
    • 不存在则执行完整上传流程
  3. 存储优化

    • 相同哈希值的文件只存储一份物理文件
    • 使用文件哈希作为存储路径依据

三、服务端实现(Spring Boot)

1. 添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.16.0</version>
</dependency>

2. 文件校验接口

@RestController
@RequestMapping("/api/file")
public class FileController {
    
    @Autowired
    private FileService fileService;

    // 秒传验证接口
    @PostMapping("/quick-verify")
    public ResponseEntity<?> verifyFile(@RequestParam String fileHash) {
        boolean exists = fileService.checkFileExists(fileHash);
        return ResponseEntity.ok(Map.of("exists", exists));
    }

    // 完整上传接口
    @PostMapping("/upload")
    public ResponseEntity<?> uploadFile(
            @RequestParam MultipartFile file,
            @RequestParam String fileHash) throws IOException {
        return fileService.processUpload(file, fileHash);
    }
}

3. 文件服务实现

@Service
public class FileService {
    
    @Value("${file.upload-dir}")
    private String uploadPath;

    public boolean checkFileExists(String fileHash) {
        Path path = Paths.get(uploadPath, fileHash.substring(0,2), fileHash);
        return Files.exists(path);
    }

    public ResponseEntity<?> processUpload(MultipartFile file, String fileHash) 
        throws IOException {
        
        // 双重校验防止并发问题
        if (checkFileExists(fileHash)) {
            return ResponseEntity.ok(Map.of("url", getFileUrl(fileHash)));
        }

        // 保存文件到指定路径(按哈希分目录存储)
        String filename = file.getOriginalFilename();
        String fileExtension = filename.substring(filename.lastIndexOf("."));
        Path directory = Paths.get(uploadPath, fileHash.substring(0,2));
        Path targetPath = directory.resolve(fileHash + fileExtension);

        Files.createDirectories(directory);
        file.transferTo(targetPath.toFile());

        return ResponseEntity.ok(Map.of("url", targetPath.toString()));
    }
}

四、前端实现(Vue.js示例)

1. 文件哈希计算

async function calculateFileHash(file) {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.readAsArrayBuffer(file);
    reader.onload = async (e) => {
      const buffer = e.target.result;
      const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
      const hashArray = Array.from(new Uint8Array(hashBuffer));
      const hashHex = hashArray
        .map(b => b.toString(16).padStart(2, '0'))
        .join('');
      resolve(hashHex);
    };
  });
}

2. 上传流程控制

async function uploadFile(file) {
  // 计算文件哈希
  const fileHash = await calculateFileHash(file);
  
  // 秒传验证
  const { data } = await axios.post('/api/file/quick-verify', {
    fileHash: fileHash
  });

  if (data.exists) {
    alert('文件秒传成功!');
    return;
  }

  // 执行完整上传
  const formData = new FormData();
  formData.append('file', file);
  formData.append('fileHash', fileHash);
  
  const result = await axios.post('/api/file/upload', formData, {
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  });
  
  console.log('上传结果:', result.data);
}

五、优化方案

  1. 分片计算哈希

    • 大文件采用分片计算方式,避免内存溢出
    • 使用Web Worker进行后台计算
  2. 存储策略优化

    // 按哈希前两位创建子目录
    Path directory = Paths.get(uploadPath, 
        fileHash.substring(0,2), 
        fileHash.substring(2,4));
    
  3. Redis缓存加速

    @Cacheable(value = "fileHashes", key = "#fileHash")
    public boolean checkFileExists(String fileHash) {
        // 数据库或文件系统查询
    }
    
  4. 断点续传集成

    • 结合分片上传实现断点续传
    • 已上传分片信息存储到Redis

六、测试验证

  1. 首次上传:

    • 正常走完整上传流程
    • 返回200状态码和文件URL
  2. 重复上传:

    • 返回秒传响应(HTTP 304)
    • 响应时间小于100ms

七、注意事项

  1. 哈希算法选择:

    • MD5:计算快但有碰撞风险
    • SHA-256:安全性高但计算稍慢
  2. 安全性:

    • 文件类型白名单校验
    • 文件大小限制
  3. 异常处理:

    • 哈希计算失败重试机制
    • 网络中断自动恢复

扩展建议

  1. 结合OSS对象存储实现分布式方案
  2. 添加文件分片上传功能
  3. 实现上传进度实时显示

该方案通过前后端协同校验,有效减少重复文件传输,可节省90%以上的带宽消耗,特别适用于网盘、云存储等文件密集型场景。


网站公告

今日签到

点亮在社区的每一天
去签到