精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

SpringBoot 實戰:文件上傳之秒傳、斷點續傳、分片上傳

開發 前端
在日常開發中,文件上傳的場景多種多樣。比如,在線教育平臺上的視頻資源上傳,社交平臺上的圖片分享,以及企業內部的知識文檔管理等。

文件上傳功能幾乎是每個 Web 應用不可或缺的一部分。無論是個人博客中的圖片上傳,還是企業級應用中的文檔管理,文件上傳都扮演著至關重要的角色。今天,松哥和大家來聊聊文件上傳中的幾個高級玩法——秒傳、斷點續傳和分片上傳。

一 文件上傳的常見場景

在日常開發中,文件上傳的場景多種多樣。比如,在線教育平臺上的視頻資源上傳,社交平臺上的圖片分享,以及企業內部的知識文檔管理等。這些場景對文件上傳的要求也各不相同,有的追求速度,有的注重穩定性,還有的需要考慮文件大小和安全性。因此,針對不同需求,我們有了秒傳、斷點續傳和分片上傳等解決方案。

二 秒傳、斷點上傳與分片上傳

秒傳

秒傳,顧名思義,就是幾乎瞬間完成文件上傳的過程。其實現原理是通過計算文件的哈希值(如 MD5 或 SHA-1),然后將這個唯一的標識符發送給服務器。如果服務器上已經存在相同的文件,則直接返回成功信息,避免了重復上傳。這種方式不僅節省了帶寬,也大大提高了用戶體驗。

斷點續傳

斷點續傳是指在網絡不穩定或者用戶主動中斷上傳后,能夠從上次中斷的地方繼續上傳,而不需要重新開始整個過程。這對于大文件上傳尤為重要,因為它可以有效防止因網絡問題導致的上傳失敗,同時也能節約用戶的流量和時間。

分片上傳

分片上傳則是將一個大文件分割成多個小塊分別上傳,最后再由服務器合并成完整的文件。這種做法的好處是可以并行處理多個小文件,提高上傳效率;同時,如果某一部分上傳失敗,只需要重傳這一部分,不影響其他部分。

三 秒傳實戰

后端實現

在 SpringBoot 項目中,我們可以使用 MessageDigest 類來計算文件的 MD5 值,然后檢查數據庫中是否存在該文件。

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

    @PostMapping("/upload1")
    public ResponseEntity<String> secondUpload(@RequestParam(value = "file",required = false) MultipartFile file,@RequestParam(required = false,value = "md5") String md5) {
        try {
            // 檢查數據庫中是否已存在該文件
            if (fileService.existsByMd5(md5)) {
                return ResponseEntity.ok("文件已存在");
            }
            // 保存文件到服務器
            file.transferTo(new File("/path/to/save/" + file.getOriginalFilename()));
            // 保存文件信息到數據庫
            fileService.save(new FileInfo(file.getOriginalFilename(), DigestUtils.md5DigestAsHex(file.getInputStream())));
            return ResponseEntity.ok("上傳成功");
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("上傳失敗");
        }
    }
}

前端調用

前端可以通過 JavaScript 的 FileReader API 讀取文件內容,通過 spark-md5 計算 MD5 值,然后發送給后端進行校驗。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>秒傳</title>
    <script src="spark-md5.js"></script>
</head>
<body>
<input type="file" id="fileInput" />
<button onclick="startUpload()">開始上傳</button>
<hr>
<script>
    async function startUpload() {
        const fileInput = document.getElementById('fileInput');
        const file = fileInput.files[0];
        if (!file) {
            alert("請選擇文件");
            return;
        }

        const md5 = await calculateMd5(file);
        const formData = new FormData();
        formData.append('md5', md5);

        const response = await fetch('/file/upload1', {
            method: 'POST',
            body: formData
        });

        const result = await response.text();
        if (response.ok) {
            if (result != "文件已存在") {
                // 開始上傳文件
            }
        } else {
            console.error("上傳失敗: " + result);
        }
    }

    function calculateMd5(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onloadend = () => {
                const spark = new SparkMD5.ArrayBuffer();
                spark.append(reader.result);
                resolve(spark.end());
            };
            reader.onerror = () => reject(reader.error);
            reader.readAsArrayBuffer(file);
        });
    }
</script>
</body>
</html>

前端分為兩個步驟:

  1. 計算文件的 MD5 值,計算之后發送給服務端確定文件是否存在。
  2. 如果文件已經存在,則不需要繼續上傳文件;如果文件不存在,則開始上傳文件,上傳文件和 MD5 校驗請求類似,上面的案例代碼中我就沒有重復演示了,松哥在書里和之前的課程里都多次講過文件上傳,這里不再啰嗦。

四 分片上傳實戰

分片上傳關鍵是在前端對文件切片,比如一個 10MB 的文件切為 10 份,每份 1MB。每次上傳的時候,需要多一個參數記錄當前上傳的文件切片的起始位置。

比如一個 10MB 的文件,切為 10 份,每份 1MB,那么:

  • 第 0 片,從 0 開始,一共是 1024*1024 個字節。
  • 第 1 片,從 1024*1024 開始,一共是 1024*1024 個字節。
  • 第 2 片...

把這個搞懂,后面的代碼就好理解了。

后端實現

private static final String UPLOAD_DIR = System.getProperty("user.home") + "/uploads/";
/**
 * 上傳文件到指定位置
 *
 * @param file 上傳的文件
 * @param start 文件開始上傳的位置
 * @return ResponseEntity<String> 上傳結果
 */
@PostMapping("/upload2")
public ResponseEntity<String> resumeUpload(@RequestParam("file") MultipartFile file, @RequestParam("start") long start,@RequestParam("fileName") String fileName) {
    try {
        File directory = new File(UPLOAD_DIR);
        if (!directory.exists()) {
            directory.mkdirs();
        }
        File targetFile = new File(UPLOAD_DIR + fileName);
        RandomAccessFile randomAccessFile = new RandomAccessFile(targetFile, "rw");
        FileChannel channel = randomAccessFile.getChannel();
        channel.position(start);
        channel.transferFrom(file.getResource().readableChannel(), start, file.getSize());
        channel.close();
        randomAccessFile.close();
        return ResponseEntity.ok("上傳成功");
    } catch (Exception e) {
        System.out.println("上傳失敗: "+e.getMessage());
        return ResponseEntity.status(500).body("上傳失敗");
    }
}

后端每次處理的時候,需要先設置文件的起始位置。

前端調用

前端需要將文件切分成多個小塊,然后依次上傳。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>分片示例</title>
</head>
<body>
    <input type="file" id="fileInput" />
    <button onclick="startUpload()">開始上傳</button>

    <script>
        async function startUpload() {
            const fileInput = document.getElementById('fileInput');
            const file = fileInput.files[0];
            if (!file) {
                alert("請選擇文件");
                return;
            }

            const filename = file.name;
            let start = 0;

            uploadFile(file, start);
        }

        async function uploadFile(file, start) {
            const chunkSize = 1024 * 1024; // 每個分片1MB
            const total = Math.ceil(file.size / chunkSize);

            for (let i = 0; i < total; i++) {
                const chunkStart = start + i * chunkSize;
                const chunkEnd = Math.min(chunkStart + chunkSize, file.size);
                const chunk = file.slice(chunkStart, chunkEnd);

                const formData = new FormData();
                formData.append('file', chunk);
                formData.append('start', chunkStart);
                formData.append('fileName', file.name);

                const response = await fetch('/file/upload2', {
                    method: 'POST',
                    body: formData
                });

                const result = await response.text();
                if (response.ok) {
                    console.log(`分片 ${i + 1}/${total} 上傳成功`);
                } else {
                    console.error(`分片 ${i + 1}/${total} 上傳失敗: ${result}`);
                    break;
                }
            }
        }
    </script>
</body>
</html>

五 斷點續傳實戰

斷點續傳的技術原理類似于分片上傳。

當文件已經上傳了一部分之后,斷了需要重新開始上傳。

那么我們的思路是這樣的:

  1. 前端先發送一個請求,檢查要上傳的文件在服務端是否已經存在,如果存在,目前大小是多少。
  2. 前端根據已經存在的大小,繼續上傳文件即可。

后端案例

先來看后端檢查的接口,如下:

@GetMapping("/check")
public ResponseEntity<Long> checkFile(@RequestParam("filename") String filename) {
    File file = new File(UPLOAD_DIR + filename);
    if (file.exists()) {
        return ResponseEntity.ok(file.length());
    } else {
        return ResponseEntity.ok(0L);
    }
}

如果文件存在,則返回已經存在的文件大小。

如果文件不存在,則返回 0,表示前端從頭開始上傳該文件。

前端調用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>斷點續傳示例</title>
</head>
<body>
<input type="file" id="fileInput"/>
<button onclick="startUpload()">開始上傳</button>

<script>
    async function startUpload() {
        const fileInput = document.getElementById('fileInput');
        const file = fileInput.files[0];
        if (!file) {
            alert("請選擇文件");
            return;
        }

        const filename = file.name;
        let start = await checkFile(filename);

        uploadFile(file, start);
    }

    async function checkFile(filename) {
        const response = await fetch(`/file/check?filename=${filename}`);
        const start = await response.json();
        return start;
    }

    async function uploadFile(file, start) {
        const chunkSize = 1024 * 1024; // 每個分片1MB
        const total = Math.ceil((file.size - start) / chunkSize);

        for (let i = 0; i < total; i++) {
            const chunkStart = start + i * chunkSize;
            const chunkEnd = Math.min(chunkStart + chunkSize, file.size);
            const chunk = file.slice(chunkStart, chunkEnd);

            const formData = new FormData();
            formData.append('file', chunk);
            formData.append('start', chunkStart);
            formData.append('fileName', file.name);

            const response = await fetch('/file/upload2', {
                method: 'POST',
                body: formData
            });

            const result = await response.text();
            if (response.ok) {
                console.log(`分片 ${i + 1}/${total} 上傳成功`);
            } else {
                console.error(`分片 ${i + 1}/${total} 上傳失敗: ${result}`);
                break;
            }
        }
    }
</script>
</body>
</html>

這個案例實際上是一個斷點續傳+分片上傳的案例,相關知識點并不難,小伙伴們可以自行體會下。

六 總結

好了,以上就是關于文件上傳中秒傳、斷點續傳和分片上傳的實戰分享。通過這些技術的應用,我們可以極大地提升文件上傳的效率和穩定性,改善用戶體驗。希望各位小伙伴在自己的項目中也能靈活運用這些技巧,解決實際問題。


責任編輯:武曉燕 來源: 江南一點雨
相關推薦

2021-01-15 11:40:44

文件Java秒傳

2022-06-15 09:01:45

大文件秒傳分片上傳

2025-10-29 04:15:00

OSS分片CDN

2025-07-03 07:41:34

2017-08-08 08:45:44

前端文件斷點續傳

2023-06-20 19:57:13

2011-03-04 16:41:57

FileZilla

2020-04-02 20:07:17

前端vuenote.js

2023-03-09 12:04:38

Spring文件校驗

2021-01-18 05:19:11

數字指紋

2022-08-05 08:40:37

架構

2013-07-22 14:02:17

iOS開發ASIHTTPRequ

2009-08-28 15:38:49

C#實現斷點續傳

2024-07-02 10:18:18

2025-07-02 00:00:00

2025-06-27 02:32:00

2017-12-20 15:11:48

iOS緩存文件斷點機制

2025-06-17 08:39:43

2011-03-01 14:12:12

FreebsdProftpd

2009-11-16 10:49:43

PHP上傳文件代碼
點贊
收藏

51CTO技術棧公眾號

国产免费播放一区二区| 日本免费一区视频| 99精品综合| 欧美一区二区精品在线| 成人免费a级片| 久久99久久| 国产综合色视频| 91精品国产色综合| 日日操免费视频| 久久草在线视频| 欧美另类z0zxhd电影| 日本韩国欧美在线观看| 免费a级人成a大片在线观看| 成人av资源站| 国产日韩精品一区二区| 日韩av在线播| 亚洲啊v在线观看| 日韩精品在线播放| 1314成人网| se01亚洲视频| 亚洲成人av中文| 中文字幕欧美日韩一区二区| 亚洲日本中文字幕在线| 狠狠v欧美v日韩v亚洲ⅴ| 7777精品视频| 国产一二三四在线| 先锋资源久久| 影音先锋日韩有码| 精品黑人一区二区三区观看时间| 精品一区91| 欧美日韩午夜在线| av五月天在线| 欧美专区福利免费| 精品人伦一区二区三区蜜桃免费| 三级在线免费观看| 伦xxxx在线| 国产欧美1区2区3区| 国内不卡一区二区三区| 亚洲av无码一区二区三区性色| 麻豆精品视频在线观看免费 | 91在线免费网站| 国产精品51麻豆cm传媒| 久久精品免费| 欧洲精品毛片网站| 国产一级精品视频| 亚洲美女视频在线免费观看| 九九九久久国产免费| 91免费公开视频| 波多野结衣一区| 中文字幕日韩高清| 国产又粗又长又硬| 久久精品99久久无色码中文字幕| 国产一区二区三区久久精品 | 91精品国产沙发| 国产一级片免费| 影音先锋久久资源网| 欧美大片大片在线播放| 国产精品白浆一区二小说| 狠久久av成人天堂| 国外色69视频在线观看| 国产奶水涨喷在线播放| 在线亚洲伦理| 国产精品jizz在线观看麻豆| 91视频久久久| 久草精品在线观看| 97se亚洲综合在线| 好吊色在线观看| 26uuu国产日韩综合| 欧美日本亚洲| 天堂аⅴ在线地址8| 专区另类欧美日韩| 国产妇女馒头高清泬20p多| 小h片在线观看| 在线欧美小视频| 国产一区二区在线观看免费视频| 国产精品1区在线| 精品毛片乱码1区2区3区 | 亚欧洲精品视频在线观看| 亚洲欧美日韩天堂一区二区| 受虐m奴xxx在线观看| 欧美视频免费| 欧美黑人一级爽快片淫片高清| 国产精品第一页在线观看| 老司机精品视频网站| 国产欧美中文字幕| 亚洲爆乳无码一区二区三区| 91蜜桃网址入口| 致1999电视剧免费观看策驰影院| 亚洲小说区图片区都市| 欧美日韩激情网| 福利片一区二区三区| jizz久久精品永久免费| 国产小视频91| 精品亚洲永久免费| 爽好多水快深点欧美视频| 91久久久久久久久久久| 污污视频在线观看网站| 国产精品久久久久久久久果冻传媒 | 91av在线免费播放| 欧州一区二区三区| 亚洲免费影视第一页| 日韩成人短视频| 国产视频久久| 91久久极品少妇xxxxⅹ软件| 国产精品ⅴa有声小说| 亚洲综合在线免费观看| 国产专区一区二区| 亚洲精品有码在线| 亚洲乱码国产乱码精品精的特点| 国产精品www994| 樱花草涩涩www在线播放| 亚洲成人中文字幕在线| 4438x全国最大成人| 神马一区二区影院| 久久久蜜桃一区二区| 国产一区二区在线影院| 美乳视频一区二区| av黄色在线| 欧美三级日韩在线| 国产一级二级视频| 午夜日韩激情| 国产美女直播视频一区| 日本中文字幕一区二区有码在线 | 日本成人在线播放| 岛国av一区二区在线在线观看| 国产乱码一区二区三区四区| 久久综合影院| 欧美一级电影久久| 日韩永久免费视频| 伊人婷婷欧美激情| 色噜噜狠狠一区二区三区狼国成人| 美女精品一区最新中文字幕一区二区三区 | 亚洲三级影院| 99porn视频在线| 好吊日视频在线观看| 日本高清不卡一区| 中文幕无线码中文字蜜桃| 亚洲高清二区| 精品高清视频| 超清av在线| 亚洲精品一区二区三区福利| 1024手机在线视频| 国产一区二区按摩在线观看| 在线视频不卡一区二区三区| 免费污视频在线一区| 亚洲网站在线播放| 亚洲无码精品一区二区三区| 国产校园另类小说区| 精品久久久久久中文字幕2017| 免费一区二区| 日本一区二区三区四区视频| 黄色毛片在线观看| 欧亚一区二区三区| 免费看一级黄色| 另类中文字幕网| 亚洲一区在线直播| 国产高清亚洲| 欧美日韩xxx| 国产香蕉在线观看| 午夜a成v人精品| 素人fc2av清纯18岁| 久久成人在线| 午夜老司机精品| 亚洲欧美在线人成swag| 欧美激情第6页| 天天干天天草天天射| 欧美日韩亚洲精品内裤| 新91视频在线观看| 男女男精品视频网| 日本一二三区视频在线| 亚洲一区电影| 国产91精品久久久久| 国际av在线| 欧美乱妇15p| 国产精品30p| 久久久青草青青国产亚洲免观| 男人女人黄一级| 婷婷中文字幕一区| 国产精品久久久久久久久久久久冷 | 国产欧美中文在线| 91丨九色丨蝌蚪| 精久久久久久| 亚洲v欧美v另类v综合v日韩v| 祥仔av免费一区二区三区四区| 欧美成人午夜激情视频| 日韩三级电影网| 欧美精品视频www在线观看| 久久国产一级片| 久久一日本道色综合| 性生活免费在线观看| 亚洲激情综合| 亚洲国产一区二区精品视频| 136福利精品导航| 国产成人精品一区二区| 超碰在线无需免费| 亚洲精品日韩久久久| 国产乱人乱偷精品视频| 亚洲线精品一区二区三区八戒| 欧美三级视频网站| 国产成人自拍网| 手机看片福利日韩| 在线精品观看| 永久久久久久| 婷婷综合一区| 99久久无色码| 国产精品久久久久久妇女| 91精品国产乱码久久久久久蜜臀 | 亚洲精品国产第一综合99久久| av网站免费在线播放| 国产精品一二三在| 国产又黄又猛又粗| 中文在线一区| 黄色片免费在线观看视频| 成人一区而且| 六月婷婷久久| 麻豆一区二区| 91久久极品少妇xxxxⅹ软件| 成人午夜sm精品久久久久久久| 午夜精品久久久久久99热| 黄色成人在线| 亚洲最新中文字幕| 日韩在线免费播放| 精品剧情v国产在线观看在线| 国产又粗又猛又黄| 色丁香久综合在线久综合在线观看| 久操视频免费在线观看| 亚洲国产精品av| 无码人妻精品一区二区中文| 成人av片在线观看| 少妇极品熟妇人妻无码| 精品一区二区三区日韩| 日韩一区二区三区不卡视频| 亚洲综合精品| 少妇高潮喷水在线观看| 欧美午夜不卡| 日本高清视频免费在线观看| 婷婷伊人综合| 宅男噜噜99国产精品观看免费| 国内精品久久久久久99蜜桃| 欧美日韩高清免费| 岛国精品一区| 国产欧美日韩一区| 极品束缚调教一区二区网站| 国产精品区免费视频| 亚洲视频三区| 国产精品果冻传媒潘| 91成人短视频| 国产日韩欧美二区| 日韩电影不卡一区| 久久综合九色综合网站| 亚洲人成网77777色在线播放 | 青青草在线播放| 亚洲精品视频免费在线观看| 色视频在线观看福利| 亚洲乱码一区二区| 免费在线国产| 在线观看视频99| 日韩精品毛片| 欧美成人精品一区二区三区| 日本乱理伦在线| 久久久久久久久久久免费| caoporn-草棚在线视频最| 久久久久日韩精品久久久男男| 岛国av在线网站| 欧美重口另类videos人妖| 欧美黑人粗大| 国产日韩专区在线| 深夜激情久久| 免费国产一区| 区一区二视频| 中文字幕の友人北条麻妃| 红桃视频国产一区| 男人的天堂99| 久色婷婷小香蕉久久| 亚洲天堂一区二区在线观看| 成人一级黄色片| 免费看裸体网站| 亚洲视频一二三| 日本一本高清视频| 欧美无人高清视频在线观看| 国产精品一区二区av白丝下载| 日韩丝袜情趣美女图片| 深夜福利免费在线观看| 日韩一级裸体免费视频| ****av在线网毛片| 国产精品欧美一区二区三区奶水 | 欧美在线一区二区三区四区| 91中文字幕精品永久在线| 国产精品入口芒果| 日韩经典中文字幕一区| 杨幂一区二区国产精品| 久久青草国产手机看片福利盒子| 男人av资源站| 疯狂做受xxxx高潮欧美日本| 亚洲永久精品视频| 日韩精品免费在线播放| 麻豆网站在线| 欧美在线视频免费播放| 国产一区二区视频在线看| 欧美精品一区二区视频| 中文在线日韩| 中国黄色片免费看| 99re热视频精品| 精品欧美一区二区久久久久| 色婷婷一区二区三区四区| 亚洲第一精品网站| 尤物九九久久国产精品的分类 | 日韩av免费看网站| 亚洲码欧美码一区二区三区| 久久99精品久久久久久秒播放器 | 中国极品少妇xxxx| 国产精品高潮呻吟av| 丝袜亚洲另类丝袜在线| 99精品视频播放| 懂色av一区二区在线播放| 免费观看特级毛片| 欧美三级免费观看| 亚洲国产精品久久久久爰性色 | 亚洲三级视频| 日本黄色一级网站| 国产精品电影一区二区| 天堂网中文字幕| 欧美精品一区二区三区蜜臀| 午夜看片在线免费| 国产成人一区二区三区| 日本亚洲不卡| 妞干网在线视频观看| 懂色av中文字幕一区二区三区| 波多野结衣在线网址| 欧美日本一区二区在线观看| 国产福利在线观看| 国产不卡av在线免费观看| 女人抽搐喷水高潮国产精品| 成人在线国产视频| 国产精品影视在线观看| 日本裸体美女视频| 欧美无砖专区一中文字| 亚洲图片88| 国产在线拍偷自揄拍精品| 水蜜桃久久夜色精品一区| 欧美一级特黄a| 国产精品久久久久9999吃药| 中文字幕精品视频在线观看| proumb性欧美在线观看| 欧美尺度大的性做爰视频| 成人激情五月天| av在线播放一区二区| 一区二区三区在线观看欧美 | 在线播放高清视频www| 国产黄色精品网站| 欧美在线免费视频| 欧美激情aaa| 亚洲ab电影| 日韩中文第一页| 日本精品另类| 水蜜桃亚洲精品| 久久精品国产99久久6| wwwww黄色| 正在播放亚洲一区| 伊人手机在线| 国产精品一区二区三区四区五区| 亚洲福利国产| 欧美老熟妇乱大交xxxxx| 成人综合在线观看| 97久久国产精品| 黄色片中文字幕| 欧美午夜影院| 久久精品国产综合| 免费看黄色av| 精品久久免费| 日韩欧美在线免费观看| 麻豆成人av| 国产黄色高清视频| 日韩制服丝袜先锋影音| 欧美大成色www永久网站婷| 特级西西人体wwwww| 99久久婷婷国产综合精品青牛牛 | 一本色道久久88综合日韩精品| 欧美大片免费观看网址| 亚洲永久激情精品| 高清日韩电视剧大全免费| 亚洲免费在线视频观看| 中文字幕日韩在线播放| 中文字幕一区日韩精品| 国产99久久九九精品无码| 国产精品国产三级国产aⅴ中文| 国产高清第一页| 欧美伊久线香蕉线新在线| 久久综合av| 国产又黄又粗又猛又爽的视频| 欧美日韩一区二区三区免费看| 国产精品国精产品一二| 亚洲欧洲三级| 成人高清在线视频| 亚洲图片在线播放| 91av免费观看91av精品在线| 亚洲xxx拳头交| 全黄一级裸体片| 精品久久久久久综合日本欧美| 成人不卡视频|