最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語(yǔ)言實(shí)現(xiàn)大文件分片上傳與斷點(diǎn)續(xù)傳功能

 更新時(shí)間:2025年09月13日 11:21:55   作者:楓葉V  
在現(xiàn)代 Web 應(yīng)用中,大文件上傳是一個(gè)常見(jiàn)需求,為了解決這些痛點(diǎn),通常采用 分片上傳 與 斷點(diǎn)續(xù)傳 的方案,本文將帶你使用 Go 實(shí)現(xiàn)一個(gè)簡(jiǎn)易的大文件分片上傳與斷點(diǎn)續(xù)傳服務(wù),希望對(duì)大家有所幫助

在現(xiàn)代 Web 應(yīng)用中,大文件上傳是一個(gè)常見(jiàn)需求。直接上傳大文件會(huì)遇到網(wǎng)絡(luò)中斷、上傳超時(shí)、失敗后無(wú)法續(xù)傳等問(wèn)題。為了解決這些痛點(diǎn),通常采用 分片上傳斷點(diǎn)續(xù)傳 的方案。

本文將帶你使用 Go 實(shí)現(xiàn)一個(gè)簡(jiǎn)易的大文件分片上傳與斷點(diǎn)續(xù)傳服務(wù)。

核心思路

1.分片上傳

將大文件切分成多個(gè)小塊(chunk),逐塊上傳,避免單次上傳過(guò)大失敗。

2.斷點(diǎn)續(xù)傳

每個(gè)文件有唯一的標(biāo)識(shí)(如 MD5、UUID),服務(wù)端記錄已上傳的分片信息,上傳中斷后可繼續(xù)上傳剩余分片。

.3合并分片

當(dāng)所有分片上傳完成后,服務(wù)端將這些分片按順序合并成完整文件。

服務(wù)端實(shí)現(xiàn)

上傳接口設(shè)計(jì)

  • 初始化上傳:生成 uploadId,返回客戶(hù)端。
  • 上傳分片/upload/chunk?uploadId=xxx&chunkIndex=1
  • 合并分片:所有分片傳完后,調(diào)用 /upload/merge 合并。

Go 代碼示例

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
)

// 臨時(shí)存放分片目錄
const uploadDir = "./uploads"

func main() {
	// 創(chuàng)建目錄
	os.MkdirAll(uploadDir, os.ModePerm)

	http.HandleFunc("/upload/chunk", uploadChunkHandler)
	http.HandleFunc("/upload/merge", mergeChunksHandler)

	fmt.Println("服務(wù)已啟動(dòng): http://localhost:8080")
	http.ListenAndServe(":8080", nil)
}

// 上傳分片
func uploadChunkHandler(w http.ResponseWriter, r *http.Request) {
	uploadId := r.URL.Query().Get("uploadId")
	chunkIndex := r.URL.Query().Get("chunkIndex")

	if uploadId == "" || chunkIndex == "" {
		http.Error(w, "缺少參數(shù)", http.StatusBadRequest)
		return
	}

	// 保存分片目錄
	chunkDir := filepath.Join(uploadDir, uploadId)
	os.MkdirAll(chunkDir, os.ModePerm)

	// 分片文件路徑
	chunkPath := filepath.Join(chunkDir, chunkIndex)

	// 寫(xiě)入文件
	file, err := os.Create(chunkPath)
	if err != nil {
		http.Error(w, "無(wú)法保存分片", http.StatusInternalServerError)
		return
	}
	defer file.Close()

	_, err = io.Copy(file, r.Body)
	if err != nil {
		http.Error(w, "寫(xiě)入分片失敗", http.StatusInternalServerError)
		return
	}

	w.Write([]byte("分片上傳成功: " + chunkIndex))
}

// 合并分片
func mergeChunksHandler(w http.ResponseWriter, r *http.Request) {
	uploadId := r.URL.Query().Get("uploadId")
	totalChunks := r.URL.Query().Get("totalChunks")

	if uploadId == "" || totalChunks == "" {
		http.Error(w, "缺少參數(shù)", http.StatusBadRequest)
		return
	}

	chunkDir := filepath.Join(uploadDir, uploadId)
	mergedFile := filepath.Join(uploadDir, uploadId+"_merged")

	// 創(chuàng)建目標(biāo)文件
	dst, err := os.Create(mergedFile)
	if err != nil {
		http.Error(w, "無(wú)法創(chuàng)建合并文件", http.StatusInternalServerError)
		return
	}
	defer dst.Close()

	// 合并分片
	chunkCount, _ := strconv.Atoi(totalChunks)
	for i := 1; i <= chunkCount; i++ {
		chunkPath := filepath.Join(chunkDir, strconv.Itoa(i))
		src, err := os.Open(chunkPath)
		if err != nil {
			http.Error(w, fmt.Sprintf("缺少分片 %d", i), http.StatusBadRequest)
			return
		}

		_, err = io.Copy(dst, src)
		src.Close()
		if err != nil {
			http.Error(w, "合并失敗", http.StatusInternalServerError)
			return
		}
	}

	w.Write([]byte("文件合并完成: " + mergedFile))
}

客戶(hù)端實(shí)現(xiàn)思路

前端/客戶(hù)端需要

  • 將文件分割為多個(gè) 固定大小的 chunk。
  • 順序調(diào)用 /upload/chunk 上傳分片。
  • 上傳完成后調(diào)用 /upload/merge 合并文件。
  • 如果上傳中斷,查詢(xún)已上傳分片,從斷點(diǎn)繼續(xù)。

示例偽代碼:

async function uploadFile(file) {
  const chunkSize = 5 * 1024 * 1024; // 5MB
  const totalChunks = Math.ceil(file.size / chunkSize);
  const uploadId = generateUploadId(file); // 可用 MD5/UUID

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

    let formData = new FormData();
    formData.append("file", chunk);

    await fetch(`/upload/chunk?uploadId=${uploadId}&chunkIndex=${i+1}`, {
      method: "POST",
      body: chunk
    });
  }

  await fetch(`/upload/merge?uploadId=${uploadId}&totalChunks=${totalChunks}`);
}

優(yōu)化點(diǎn)

分片校驗(yàn):上傳前計(jì)算 MD5,避免重復(fù)上傳。

并行上傳:可同時(shí)并發(fā)上傳多個(gè)分片,提升速度。

斷點(diǎn)續(xù)傳:服務(wù)端保存已上傳分片信息,客戶(hù)端查詢(xún)后跳過(guò)已完成分片。

秒傳功能:通過(guò)文件 Hash 判斷文件是否已存在,直接返回完成。

總結(jié)

通過(guò) Go 實(shí)現(xiàn)大文件分片上傳與斷點(diǎn)續(xù)傳,可以有效提升上傳成功率和用戶(hù)體驗(yàn)。實(shí)際項(xiàng)目中,還需要結(jié)合 數(shù)據(jù)庫(kù)記錄、鑒權(quán)、并發(fā)控制、文件存儲(chǔ)(如 OSS、S3、MinIO) 等功能,構(gòu)建更健壯的文件上傳系統(tǒng)。

到此這篇關(guān)于Go語(yǔ)言實(shí)現(xiàn)大文件分片上傳與斷點(diǎn)續(xù)傳功能的文章就介紹到這了,更多相關(guān)Go大文件上傳內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語(yǔ)言并發(fā)編程之控制并發(fā)數(shù)量實(shí)現(xiàn)實(shí)例

    Go語(yǔ)言并發(fā)編程之控制并發(fā)數(shù)量實(shí)現(xiàn)實(shí)例

    這篇文章主要為大家介紹了Go語(yǔ)言并發(fā)編程之控制并發(fā)數(shù)量實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Go作用域的理解

    Go作用域的理解

    在Go語(yǔ)言中,作用域是指變量的可見(jiàn)性范圍,它定義了變量在程序中的生命周期和可訪(fǎng)問(wèn)性,本文主要介紹了Go作用域的理解,包括局部作用域、全局作用域、命名空間作用域等,感興趣的可以了解一下
    2023-11-11
  • Golang切片連接成字符串的實(shí)現(xiàn)示例

    Golang切片連接成字符串的實(shí)現(xiàn)示例

    本文主要介紹了Golang切片連接成字符串的實(shí)現(xiàn)示例,可以使用Go語(yǔ)言中的內(nèi)置函數(shù)"String()"可以將字節(jié)切片轉(zhuǎn)換為字符串,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • 基于Go語(yǔ)言實(shí)現(xiàn)一個(gè)并發(fā)下載器

    基于Go語(yǔ)言實(shí)現(xiàn)一個(gè)并發(fā)下載器

    這篇文章主要為大家詳細(xì)介紹了如何利用GO語(yǔ)言實(shí)現(xiàn)一個(gè)并發(fā)的文件下載器,可以在不重新啟動(dòng)整個(gè)下載的情況下處理錯(cuò)誤,感興趣的小伙伴可以了解一下
    2023-10-10
  • Go語(yǔ)言如何使用 Viper 來(lái)管理配置

    Go語(yǔ)言如何使用 Viper 來(lái)管理配置

    在現(xiàn)代軟件開(kāi)發(fā)中,良好的配置管理可以極大地提升應(yīng)用的靈活性和可維護(hù)性,下面我們就來(lái)看看GO語(yǔ)言中如何使用 Viper 來(lái)管理配置吧
    2024-11-11
  • Go語(yǔ)言中的方法定義用法分析

    Go語(yǔ)言中的方法定義用法分析

    這篇文章主要介紹了Go語(yǔ)言中的方法定義用法,實(shí)例分析了方法的定義及使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • Go語(yǔ)言使用Zap輕松搞定結(jié)構(gòu)化日志

    Go語(yǔ)言使用Zap輕松搞定結(jié)構(gòu)化日志

    在?Go?語(yǔ)言中,有許多日志庫(kù)可供選擇,但在性能和靈活性方面,Zap?是其中的佼佼者,下面我們就來(lái)看看Go?項(xiàng)目中如何使用?Zap?進(jìn)行結(jié)構(gòu)化日志記錄吧
    2024-11-11
  • go語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易比特幣系統(tǒng)錢(qián)包的原理解析

    go語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易比特幣系統(tǒng)錢(qián)包的原理解析

    這篇文章主要介紹了go語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易比特幣系統(tǒng)錢(qián)包的原理解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • Go語(yǔ)言sync.Map詳解及使用場(chǎng)景

    Go語(yǔ)言sync.Map詳解及使用場(chǎng)景

    Go語(yǔ)言中的sync.Map是一個(gè)高效的并發(fā)安全映射結(jié)構(gòu),適用于高并發(fā)讀多寫(xiě)少的場(chǎng)景,它通過(guò)讀寫(xiě)分離、無(wú)鎖讀取路徑、寫(xiě)入時(shí)的鎖保護(hù)等機(jī)制,提高了讀取性能并減少了鎖競(jìng)爭(zhēng),sync.Map不需要手動(dòng)管理鎖,降低了編程復(fù)雜性,適合需要簡(jiǎn)單并發(fā)訪(fǎng)問(wèn)的場(chǎng)合
    2024-10-10
  • 淺談Go連接池的設(shè)計(jì)與實(shí)現(xiàn)

    淺談Go連接池的設(shè)計(jì)與實(shí)現(xiàn)

    本文主要介紹了淺談Go連接池的設(shè)計(jì)與實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04

最新評(píng)論

蕉岭县| 沙雅县| 左权县| 湄潭县| 台中县| 保山市| 大庆市| 黑山县| 潍坊市| 塔河县| 冀州市| 西乌珠穆沁旗| 汤原县| 灵石县| 临沧市| 隆子县| 汤阴县| 电白县| 高雄县| 隆子县| 卫辉市| 常州市| 留坝县| 建始县| 都匀市| 双柏县| 东山县| 乐山市| 全州县| 东海县| 县级市| 桦川县| 鹰潭市| 罗定市| 平邑县| 白沙| 邯郸市| 西藏| 宁都县| 方城县| 聊城市|