首页 > 文章列表 > Golang实现文件传输功能

Golang实现文件传输功能

golang
122 2022-12-17

本文实例为大家分享了Golang实现文件传输的具体代码,供大家参考,具体内容如下

借助TCP完成文件的传输,基本思路如下:

1、发送方(客户端)向服务端发送文件名,服务端保存该文件名。

2、接收方(服务端)向客户端返回一个消息ok,确认文件名保存成功。

3、发送方(客户端)收到消息后,开始向服务端发送文件数据。

4、接收方(服务端)读取文件内容,写入到之前保存好的文件中。

首先获取文件名。借助os包中的stat()函数来获取文件属性信息。在函数返回的文件属性中包含文件名和文件大小。Stat参数name传入的是文件访问的绝对路径。FileInfo中的Name()函数可以将文件名单独提取出来。

func Stat(name string) (FileInfo, error) 

type FileInfo interface {

   Name() string       

   Size() int64        

   Mode() FileMode     

   ModTime() time.Time 

   IsDir() bool        

   Sys() interface{}   

}

发送端:

package main



import (

    "fmt"

    "io"

    "net"

    "os"

)



func sendFile(conn net.Conn, filePath string) {

    // 只读打开文件

    f, err := os.Open(filePath)

    if err != nil {

        fmt.Println("os.Open err:", err)

        return

    }

    defer f.Close()



    // 从本文件中,读数据,写给网络接收端。 读多少,写多少。原封不动。

    buf := make([]byte, 1024)

    for {

        n, err := f.Read(buf)

        if err != nil {

            if err == io.EOF {

                fmt.Println("发送文件完成。")

            } else {

                fmt.Println("os.Open err:", err)

            }

            return

        }

        // 写到网络socket中

        _, err = conn.Write(buf[:n])

        if err != nil {

            fmt.Println("conn.Write err:", err)

            return

        }

    }

}



func main() {

    list := os.Args // 获取命令行参数



    if len(list) != 2 {

        fmt.Println("格式为:go run xxx.go 文件绝对路径")

        return

    }

    // 提取 文件的绝对路径

    filePath := list[1]



    //提取文件名

    fileInfo, err := os.Stat(filePath)

    if err != nil {

        fmt.Println("os.Stat err:", err)

        return

    }

    fileName := fileInfo.Name()



    // 主动发起连接请求

    conn, err := net.Dial("tcp", "127.0.0.1:8000")

    if err != nil {

        fmt.Println("net.Dial err:", err)

        return

    }

    defer conn.Close()



    // 发送文件名给 接收端

    _, err = conn.Write([]byte(fileName))

    if err != nil {

        fmt.Println("conn.Write err:", err)

        return

    }

    // 读取服务器回发的 OK

    buf := make([]byte, 1024)

    n, err := conn.Read(buf)

    if err != nil {

        fmt.Println("conn.Read err:", err)

        return

    }



    if "ok" == string(buf[:n]) {

        // 写文件内容给服务器——借助conn

        sendFile(conn, filePath)

    }

}

接收端:

package main



import (

    "fmt"

    "net"

    "os"

)



func recvFile(conn net.Conn, fileName string) {

    // 按照文件名创建新文件

    f, err := os.Create(fileName)

    if err != nil {

        fmt.Println("os.Create err:", err)

        return

    }

    defer f.Close()



    // 从 网络中读数据,写入本地文件

    buf := make([]byte, 1024)

    for {

        n, _ := conn.Read(buf)

        if n == 0 {

            fmt.Println("接收文件完成。")

            return

        }

        // 写入本地文件,读多少,写多少。

        f.Write(buf[:n])

    }

}



func main() {

    // 创建用于监听的socket

    listener, err := net.Listen("tcp", "127.0.0.1:8000")

    if err != nil {

        fmt.Println(" net.Listen err:", err)

        return

    }

    defer listener.Close()



    fmt.Println("接收端启动成功,等待发送端发送文件!")



    // 阻塞监听

    conn, err := listener.Accept()

    if err != nil {

        fmt.Println(" listener.Accept() err:", err)

        return

    }

    defer conn.Close()



    // 获取文件名,保存

    buf := make([]byte, 1024)

    n, err := conn.Read(buf)

    if err != nil {

        fmt.Println(" conn.Read err:", err)

        return

    }

    fileName := string(buf[:n])



    // 回写 ok 给发送端

    conn.Write([]byte("ok"))



    // 获取文件内容

    recvFile(conn, fileName)

}