首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

文件上傳防重複:前端生成唯一標識 + 後端幂等性校驗

     編輯:程式設計疑難解答

核心思路

上傳前前端生成唯一 uploadId(UUID/雪花算法/時間戳+隨機數),隨文件一起傳給後端。後端用 uploadId 作為幂等性 Key,發現已處理則直接返回成功,不再重複存儲。

完整流程

前端(Vue/React/原生 JS)


function generateUploadId() {
    return Date.now().toString(36) + Math.random().toString(36).substr(2, 9);
}

async function uploadFile(file) {
    const uploadId = generateUploadId();
    const formData = new FormData();
    formData.append('file', file);
    formData.append('uploadId', uploadId);
    // 可選:將 uploadId 存入 sessionStorage 防頁面刷新重複提交
    sessionStorage.setItem('lastUploadId', uploadId);

    const res = await fetch('/api/upload', {method: 'POST', body: formData});
    return res.json();
}

後端(Spring Boot 示例)


@PostMapping("/upload")
public Result upload(@RequestParam MultipartFile file, @RequestParam String uploadId) {
    // 1. 檢查幂等性 Key(Redis SETNX 或 數據庫唯一索引)
    Boolean acquired = redisTemplate.opsForValue().setIfAbsent("upload:" + uploadId, "1", Duration.ofHours(24));
    if (!acquired) {
        return Result.success("文件已上傳,勿重複提交"); // 秒回,不再處理文件
    }

    // 2. 真正保存文件
    String path = storageService.save(file);

    // 3. 記錄文件元數據(可選)
    fileMetaRepo.save(new FileMeta(uploadId, path, file.getOriginalFilename(), file.getSize()));

    return Result.success(path);
}

關鍵點

  1. uploadId 必須由前端生成,後端生成無法防止用戶雙擊提交按鈕發起兩次請求。
  2. 幂等性檢查要在文件讀取/保存之前,避免浪費 I/O。
  3. Redis SETNX / 數據庫唯一索引 保證分佈式環境下原子性。
  4. 過期時間:幂等性 Key 保留 24h-7天,防止用戶極長時間後重試誤判。

進階:大文件分片上傳防重

分片上傳時,uploadId 標識整個文件,每片帶 chunkIndex。合併前檢查 uploadId 是否已合併完成。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved