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

Yuan_sr

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

客户端

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)
}
阅读 520
7 声望
4 粉丝
0 条评论
你知道吗?

7 声望
4 粉丝
宣传栏