乐趣区

关于golang: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("D:\\GoObject\\Gocode\\ 端点续传 \\clinet\\file_ob.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)
}
退出移动版