Go语言实现文件的断点续传

Posted Yuan_sr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go语言实现文件的断点续传相关的知识,希望对你有一定的参考价值。

本文主要简单实现一个发送文件的端点续传功能,主要解决在传输过程中客户端断开后在重新取得连接后可在之前的传输基础上进行继续传输,直到文件传输完毕。

客户端

package main

import (
    "fmt"
    "io"
    "net"
    "os"
    "strconv"
    "time"
)

func clientRead(conn net.Conn) int{
    buf := make([]byte, 10)
    n, err := conn.Read(buf)
    if err != nil {
        fmt.Println("conn.Read err:", err)
    }
    off, err := strconv.Atoi(string(buf[:n]))
    if err != nil {
        fmt.Println("strconv.Atoi err:", err)
    }
    return off
}

//发送数据
func clientWrite(conn net.Conn, data []byte){
    _, err := conn.Write(data)
    if err != nil {
        fmt.Println("conn.Write err:", err)
    }
    fmt.Println("写入数据:", string(data))
}

func clientConn(conn net.Conn) {
    defer conn.Close()
    clientWrite(conn, []byte("start-->"))
    off := clientRead(conn)
    fp, err := os.OpenFile("file.txt", os.O_RDONLY, 0777)
    if err != nil {
        fmt.Println("os.OpenFile err:", err)
    }
    defer fp.Close()

    _, err = fp.Seek(int64(off), 0)
    if err != nil {
        fmt.Println("Seek err:", err)
    }

    for{
        data := make([]byte, 10)
        n, err := fp.Read(data)
        if err != nil {
            if err == io.EOF{
                time.Sleep(time.Second)
                //clientWrite(conn, []byte("<--end"))
                fmt.Println("文件发送结束!")
                break
            }
        }
        //time.Sleep(time.Second)
        clientWrite(conn, data[:n])
    }
}

func main(){
    conn, err := net.DialTimeout("tcp", "127.0.0.1:8848", time.Second*10)
    //conn, err := net.Dial("tcp", "127.0.0.1:8848")
    if err != nil {
        fmt.Println("Dial err:", err)
    }

    clientConn(conn)
}

服务端

package main

import (
    "fmt"
    "io"
    "net"
    "os"
    "strconv"
)

//追加
func WriteFile(content []byte){
    if len(content) > 0{
        fp, err := os.OpenFile("file_out.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0777)
        if err != nil {
            fmt.Println("OpenFile err:", err)
        }
        defer fp.Close()
        _, err = fp.Write(content)
        if err != nil {
            fmt.Println("fp.Write err:", err)
        }
        fmt.Println("fp.Write ok")
    }
}

//判断文件是否存在
func getFileState() int64{
    stat, err := os.Stat("file_out.txt")
    if err != nil {
        if os.IsNotExist(err){
            fmt.Println("文件不存在")
            return 0
        }
    }
    return stat.Size()
}

func serverConn(conn net.Conn){
    defer conn.Close()
    for true {
        var buf = make([]byte, 10)
        n, err := conn.Read(buf)
        if err != nil {
            if err == io.EOF{
                fmt.Println("server is EOF")
                return
            }
            fmt.Println("conn.read err:", err)
            return
        }
        fmt.Println("收到数据:", string(buf[:n]))
        switch string(buf[:n]) {
        case "start-->":
            off := getFileState()
            stroff := strconv.FormatInt(off, 10)
            _, err := conn.Write([]byte(stroff))
            if err != nil {
                fmt.Println("conn.Write err:", err)
            }
            continue
        //case "<--end":
        //    fmt.Println("文件写入完毕!")
        //    return
        }
        WriteFile(buf[:n])
    }
}

func main(){
    listen, err := net.Listen("tcp", "127.0.0.1:8848")
    if err != nil {
        fmt.Println("net.Listen err:", err)
    }
    fmt.Println("正在监听...")
    defer listen.Close()
    conn, err := listen.Accept()
    if err != nil {
        fmt.Println("Accept err:", err)
    }
    serverConn(conn)
}

以上是关于Go语言实现文件的断点续传的主要内容,如果未能解决你的问题,请参考以下文章

大文件上传下载实现思路,分片断点续传代码实现,以及webUpload组件

Go断点续传

用java向hdfs上传文件时,如何实现断点续传

如何用Java实现HTTP断点续传功能

文件下载之断点续传(客户端与服务端的实现)

nginx-upload-module模块实现文件断点续传