首頁 > 軟體

Golang實現檔案傳輸功能

2022-07-26 14:02:24

本文範例為大家分享了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)
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com