8

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

 3 years ago
source link: https://segmentfault.com/a/1190000039990513
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

发布于 今天 15:47

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

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)
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK